From 3caec7eadbd758b8d6ae15891ed48b5465b818d5 Mon Sep 17 00:00:00 2001 From: Ken Tucker Date: Sun, 24 Nov 2024 13:51:58 -0500 Subject: [PATCH 1/4] #Refactor namespaces and enhance service locator tests Moved IService and ServiceImpl to Models namespace. Renamed ServiceLocatorTests to MSDependencyInjectionServiceLocatorTests. Added new test methods for service locator functionalities. Updated Setup class with additional ICar and IPet registrations. Enhanced MSDependencyInjectionServiceLocator to support keyed services. Added Cat and Dog classes implementing IPet interface. Added ICar interface and its implementations Ford, Toyota, and Chevy. Added IPet interface to Models namespace. --- .../Models/Cat.cs | 10 ++ .../Models/Dog.cs | 10 ++ .../Models/ICar.cs | 22 +++++ .../Models/IPet.cs | 7 ++ .../Models/IService.cs | 7 ++ .../{IService.cs => Models/ServiceImpl.cs} | 7 +- .../ServiceLocatorTests.cs | 98 ++++++++++++++++++- .../Setup.cs | 8 +- .../MSDependencyInjectionServiceLocator.cs | 32 ++++-- 9 files changed, 182 insertions(+), 19 deletions(-) create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Cat.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Dog.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IPet.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IService.cs rename vb2ae.ServiceLocator.MSDependencyInjection.Tests/{IService.cs => Models/ServiceImpl.cs} (50%) diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Cat.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Cat.cs new file mode 100644 index 0000000..eb0e555 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Cat.cs @@ -0,0 +1,10 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public class Cat : IPet + { + public string Speak() + { + return "Meow"; + } + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Dog.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Dog.cs new file mode 100644 index 0000000..185cdca --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Dog.cs @@ -0,0 +1,10 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public class Dog : IPet + { + public string Speak() + { + return "Bark"; + } + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs new file mode 100644 index 0000000..edf9d38 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs @@ -0,0 +1,22 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public interface ICar + { + string Name { get; set; } + } + + public class Ford : ICar + { + public string Name { get; set; } = "Ford"; + } + + public class Toyota : ICar + { + public string Name { get; set; } = "Toyota"; + } + + public class Chevy : ICar + { + public string Name { get; set; } = "Chevy"; + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IPet.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IPet.cs new file mode 100644 index 0000000..110a954 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IPet.cs @@ -0,0 +1,7 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public interface IPet + { + string Speak(); + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IService.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IService.cs new file mode 100644 index 0000000..42b83f7 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/IService.cs @@ -0,0 +1,7 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public interface IService + { + void DoSomething(); + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/IService.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ServiceImpl.cs similarity index 50% rename from vb2ae.ServiceLocator.MSDependencyInjection.Tests/IService.cs rename to vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ServiceImpl.cs index cbca029..b73b252 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/IService.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ServiceImpl.cs @@ -1,10 +1,5 @@ -namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models { - public interface IService - { - void DoSomething(); - } - public class ServiceImpl : IService { public void DoSomething() diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs index d54abbe..4c4387b 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs @@ -1,12 +1,100 @@ +using Microsoft.Extensions.DependencyInjection; +using vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models; + namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests { - public class ServiceLocatorTests + public class MSDependencyInjectionServiceLocatorTests { + private readonly IServiceProvider _serviceProvider; + + public MSDependencyInjectionServiceLocatorTests(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + [Fact] + public void GetAllInstances_Type_ReturnsInstances() + { + + var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(typeof(IService)); + + Assert.Single(result); + } + [Fact] + public void GetAllInstances_Type_ReturnsInstancesWhenKeyIsUsed() + { + + var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(typeof(IPet)); + + Assert.Equal(2, result.Count()); + } + [Fact] + public void GetAllInstances_Generic_ReturnsInstances() + { + var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(); + + Assert.Equal(3, result.Count()); + } + + [Fact] + public void GetAllInstances_Generic_ReturnsInstancesWithKey() + { + var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(); + + Assert.Equal(2, result.Count()); + } + + [Fact] + public void GetInstance_Type_ReturnsInstance() + { + var serviceType = typeof(IService); + + var result = CommonServiceLocator.ServiceLocator.Current.GetInstance(serviceType); + + Assert.True(result is ServiceImpl); + } + + [Fact] + public void GetInstance_Type_WithKey() + { + var serviceType = typeof(IPet); + var key = "Cat"; + + Assert.True(CommonServiceLocator.ServiceLocator.Current.GetInstance(serviceType, key) is Cat); + } + + [Fact] + public void GetInstance_Generic_ReturnsInstance() + { + var result = CommonServiceLocator.ServiceLocator.Current.GetInstance(); + + Assert.True(result is IService); + } + + [Fact] + public void GetInstance_Generic_WithKey() + { + var key = "Dog"; + + Assert.True(CommonServiceLocator.ServiceLocator.Current.GetInstance(key) is Dog); + } + + [Fact] + public void GetService_Generic_ReturnsService() + { + var result = CommonServiceLocator.ServiceLocator.Current.GetService(); + + Assert.True(result is IService); + } + [Fact] - public void VerifyServiceLocatorCanLoadClass() + public void GetService_Type_ReturnsService() { - var service = CommonServiceLocator.ServiceLocator.Current.GetInstance(); - Assert.NotNull(service); + var serviceType = typeof(IService); + + var result = CommonServiceLocator.ServiceLocator.Current.GetService(serviceType); + + Assert.True(result is IService); } } -} \ No newline at end of file +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Setup.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Setup.cs index f1859d3..6e787a4 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Setup.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Setup.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models; namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests { @@ -23,8 +24,11 @@ private IServiceProvider Build() _defaultBuilder.ConfigureServices((context, services) => { services.AddSingleton(); - // where ServiceImpl implements IService - // ... add other services when needed + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddKeyedTransient("Dog"); + services.AddKeyedTransient("Cat"); }); _services = _defaultBuilder.Build().Services; diff --git a/vb2ae.ServiceLocator.MSDependencyInjection/MSDependencyInjectionServiceLocator.cs b/vb2ae.ServiceLocator.MSDependencyInjection/MSDependencyInjectionServiceLocator.cs index 1b5ee1f..ee8cc4f 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection/MSDependencyInjectionServiceLocator.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection/MSDependencyInjectionServiceLocator.cs @@ -16,12 +16,34 @@ public MSDependencyInjectionServiceLocator(IServiceProvider serviceProvider) public IEnumerable GetAllInstances(Type serviceType) { - return _serviceProvider.GetServices(serviceType); + var allServices = new List(); + var services = _serviceProvider.GetServices(serviceType); + if (services != null) + { + allServices.AddRange(services); + } + var keyedServices = _serviceProvider.GetKeyedServices(serviceType, KeyedService.AnyKey); + if (keyedServices != null) + { + allServices.AddRange(keyedServices); + } + return allServices; } public IEnumerable GetAllInstances() { - return _serviceProvider.GetServices(); + var allServices = new List(); + var services = _serviceProvider.GetServices(); + if (services != null) + { + allServices.AddRange(services); + } + var keyedServices = _serviceProvider.GetKeyedServices(KeyedService.AnyKey); + if (keyedServices != null) + { + allServices.AddRange(keyedServices); + } + return allServices; } public object GetInstance(Type serviceType) @@ -33,7 +55,7 @@ public object GetInstance(Type serviceType, string key) { // Microsoft.Extensions.DependencyInjection does not support keyed services out of the box. // You might need to implement a custom logic or use a third-party library for this. - throw new NotSupportedException("Keyed services are not supported."); + return _serviceProvider.GetRequiredKeyedService(serviceType, key); } public TService GetInstance() @@ -43,9 +65,7 @@ public TService GetInstance() public TService GetInstance(string key) { - // Microsoft.Extensions.DependencyInjection does not support keyed services out of the box. - // You might need to implement a custom logic or use a third-party library for this. - throw new NotSupportedException("Keyed services are not supported."); + return _serviceProvider.GetKeyedService(key); } public T GetService() From 147a8c94d53ef193fb8f4c1fcf3fdc0f8924a6e3 Mon Sep 17 00:00:00 2001 From: Ken Tucker Date: Sun, 24 Nov 2024 14:02:15 -0500 Subject: [PATCH 2/4] Update vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs Co-authored-by: codefactor-io[bot] <47775046+codefactor-io[bot]@users.noreply.github.com> --- .../ServiceLocatorTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs index 4c4387b..a997264 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs @@ -23,7 +23,6 @@ public void GetAllInstances_Type_ReturnsInstances() [Fact] public void GetAllInstances_Type_ReturnsInstancesWhenKeyIsUsed() { - var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(typeof(IPet)); Assert.Equal(2, result.Count()); From 2f6ee46ddefc19b0dba1264805d43d50548392a3 Mon Sep 17 00:00:00 2001 From: Ken Tucker Date: Sun, 24 Nov 2024 14:02:25 -0500 Subject: [PATCH 3/4] Update vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs Co-authored-by: codefactor-io[bot] <47775046+codefactor-io[bot]@users.noreply.github.com> --- .../ServiceLocatorTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs index a997264..f9d8633 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/ServiceLocatorTests.cs @@ -15,7 +15,6 @@ public MSDependencyInjectionServiceLocatorTests(IServiceProvider serviceProvider [Fact] public void GetAllInstances_Type_ReturnsInstances() { - var result = CommonServiceLocator.ServiceLocator.Current.GetAllInstances(typeof(IService)); Assert.Single(result); From f0b785d9e790714f51913a167e830c0861b967ea Mon Sep 17 00:00:00 2001 From: Ken Tucker Date: Sun, 24 Nov 2024 14:12:57 -0500 Subject: [PATCH 4/4] Refactor: Move car classes to separate files Moved Ford, Toyota, and Chevy classes from ICar.cs to individual files. Created Ford.cs, Toyota.cs, and Chevy.cs. Updated namespace to vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models. --- .../Models/Chevy.cs | 7 +++++++ .../Models/Ford.cs | 7 +++++++ .../Models/ICar.cs | 15 --------------- .../Models/Toyota.cs | 7 +++++++ 4 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Chevy.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Ford.cs create mode 100644 vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Toyota.cs diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Chevy.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Chevy.cs new file mode 100644 index 0000000..3e12301 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Chevy.cs @@ -0,0 +1,7 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public class Chevy : ICar + { + public string Name { get; set; } = "Chevy"; + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Ford.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Ford.cs new file mode 100644 index 0000000..c0889a3 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Ford.cs @@ -0,0 +1,7 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public class Ford : ICar + { + public string Name { get; set; } = "Ford"; + } +} diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs index edf9d38..1a17f23 100644 --- a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/ICar.cs @@ -4,19 +4,4 @@ public interface ICar { string Name { get; set; } } - - public class Ford : ICar - { - public string Name { get; set; } = "Ford"; - } - - public class Toyota : ICar - { - public string Name { get; set; } = "Toyota"; - } - - public class Chevy : ICar - { - public string Name { get; set; } = "Chevy"; - } } diff --git a/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Toyota.cs b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Toyota.cs new file mode 100644 index 0000000..62daed0 --- /dev/null +++ b/vb2ae.ServiceLocator.MSDependencyInjection.Tests/Models/Toyota.cs @@ -0,0 +1,7 @@ +namespace vb2ae.ServiceLocator.MSDependencyInjection.Tests.Models +{ + public class Toyota : ICar + { + public string Name { get; set; } = "Toyota"; + } +}