From 77e158f564c5b3e7637a4d4b08febe4acb4009ec Mon Sep 17 00:00:00 2001 From: Simon Gockner Date: Fri, 7 Jun 2019 10:15:04 +0200 Subject: [PATCH] #6: start refactoring `Injector` to Ioc --- .../Exceptions/InternalResolveException.cs | 2 +- .../Exceptions/TypeNotRegisteredException.cs | 4 +- ...IInjectorContainer.cs => IIocContainer.cs} | 12 +- ...IInjectorInstaller.cs => IIocInstaller.cs} | 10 +- .../Registrations/IDefaultRegistration.cs | 2 +- .../{InjectorContainer.cs => IocContainer.cs} | 16 +- .../Registrations/DefaultRegistration.cs | 2 +- .../Registrations/RegistrationFactory.cs | 6 +- .../Registrations/TypedFactoryRegistration.cs | 14 +- .../InjectorContainerTest.cs | 189 ------------------ .../IocContainerTest.cs | 189 ++++++++++++++++++ 11 files changed, 223 insertions(+), 223 deletions(-) rename LightweightIocContainer/Interfaces/{IInjectorContainer.cs => IIocContainer.cs} (81%) rename LightweightIocContainer/Interfaces/{IInjectorInstaller.cs => IIocInstaller.cs} (54%) rename LightweightIocContainer/{InjectorContainer.cs => IocContainer.cs} (93%) delete mode 100644 Test.LightweightIocContainer/InjectorContainerTest.cs create mode 100644 Test.LightweightIocContainer/IocContainerTest.cs diff --git a/LightweightIocContainer/Exceptions/InternalResolveException.cs b/LightweightIocContainer/Exceptions/InternalResolveException.cs index fd122b9..1413e2e 100644 --- a/LightweightIocContainer/Exceptions/InternalResolveException.cs +++ b/LightweightIocContainer/Exceptions/InternalResolveException.cs @@ -8,7 +8,7 @@ using LightweightIocContainer.Interfaces; namespace LightweightIocContainer.Exceptions { /// - /// An internal Error happened while the tried to resolve an instance + /// An internal Error happened while the tried to resolve an instance /// public class InternalResolveException : Exception { diff --git a/LightweightIocContainer/Exceptions/TypeNotRegisteredException.cs b/LightweightIocContainer/Exceptions/TypeNotRegisteredException.cs index 9d88e67..0e89e22 100644 --- a/LightweightIocContainer/Exceptions/TypeNotRegisteredException.cs +++ b/LightweightIocContainer/Exceptions/TypeNotRegisteredException.cs @@ -8,12 +8,12 @@ using LightweightIocContainer.Interfaces; namespace LightweightIocContainer.Exceptions { /// - /// The Type is not registered in this + /// The Type is not registered in this /// public class TypeNotRegisteredException : Exception { public TypeNotRegisteredException(Type type) - : base($"Type {type.Name} is not registered in this InjectorContainer.") + : base($"Type {type.Name} is not registered in this IocContainer.") { Type = type; } diff --git a/LightweightIocContainer/Interfaces/IInjectorContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs similarity index 81% rename from LightweightIocContainer/Interfaces/IInjectorContainer.cs rename to LightweightIocContainer/Interfaces/IIocContainer.cs index 2251175..27dcf31 100644 --- a/LightweightIocContainer/Interfaces/IInjectorContainer.cs +++ b/LightweightIocContainer/Interfaces/IIocContainer.cs @@ -10,17 +10,17 @@ namespace LightweightIocContainer.Interfaces /// /// The main container that carries all the s and can resolve all the types you'll ever want /// - public interface IInjectorContainer : IDisposable + public interface IIocContainer : IDisposable { /// - /// Install the given installers for the current + /// Install the given installers for the current /// - /// The given s - /// An instance of the current - IInjectorContainer Install(params IInjectorInstaller[] installers); + /// The given s + /// An instance of the current + IIocContainer Install(params IIocInstaller[] installers); /// - /// Add the to the the + /// Add the to the the /// /// The given void Register(IRegistrationBase registration); diff --git a/LightweightIocContainer/Interfaces/IInjectorInstaller.cs b/LightweightIocContainer/Interfaces/IIocInstaller.cs similarity index 54% rename from LightweightIocContainer/Interfaces/IInjectorInstaller.cs rename to LightweightIocContainer/Interfaces/IIocInstaller.cs index 91812d0..b793a5e 100644 --- a/LightweightIocContainer/Interfaces/IInjectorInstaller.cs +++ b/LightweightIocContainer/Interfaces/IIocInstaller.cs @@ -7,14 +7,14 @@ using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Interfaces { /// - /// The base class for installers + /// The base class for installers /// - public interface IInjectorInstaller + public interface IIocInstaller { /// - /// Install the needed s in the given + /// Install the needed s in the given /// - /// The current - void Install(IInjectorContainer container); + /// The current + void Install(IIocContainer container); } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs index 56428c4..b00597e 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs @@ -24,7 +24,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// /// This action is invoked when an instance of this type is created. - /// Can be set in the by calling + /// Can be set in the by calling /// Action OnCreateAction { get; } diff --git a/LightweightIocContainer/InjectorContainer.cs b/LightweightIocContainer/IocContainer.cs similarity index 93% rename from LightweightIocContainer/InjectorContainer.cs rename to LightweightIocContainer/IocContainer.cs index dd31495..f40cadb 100644 --- a/LightweightIocContainer/InjectorContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -15,17 +15,17 @@ namespace LightweightIocContainer /// /// The main container that carries all the s and can resolve all the types you'll ever want /// - public class InjectorContainer : IInjectorContainer + public class IocContainer : IIocContainer { private readonly List _registrations = new List(); private readonly List<(Type type, object instance)> _singletons = new List<(Type, object)>(); //TODO: Think about the usage of ConditionalWeakTable<> /// - /// Install the given installers for the current + /// Install the given installers for the current /// - /// The given s - /// An instance of the current - public IInjectorContainer Install(params IInjectorInstaller[] installers) + /// The given s + /// An instance of the current + public IIocContainer Install(params IIocInstaller[] installers) { foreach (var installer in installers) { @@ -36,7 +36,7 @@ namespace LightweightIocContainer } /// - /// Add the to the the + /// Add the to the the /// /// The given public void Register(IRegistrationBase registration) @@ -74,7 +74,7 @@ namespace LightweightIocContainer /// Could not find function public object Resolve(Type type, object[] arguments) //somehow the order of the arguments is different in the application compared to the unit test { - var resolveMethod = typeof(InjectorContainer).GetMethod(nameof(ResolveInternal), BindingFlags.NonPublic | BindingFlags.Instance); + var resolveMethod = typeof(IocContainer).GetMethod(nameof(ResolveInternal), BindingFlags.NonPublic | BindingFlags.Instance); var genericResolveMethod = resolveMethod?.MakeGenericMethod(type); if (genericResolveMethod == null) @@ -89,7 +89,7 @@ namespace LightweightIocContainer /// The registered type /// The constructor arguments /// An instance of the given registered type - /// The given type is not registered in this + /// The given type is not registered in this /// The registration for the given type has an unknown type private T ResolveInternal(params object[] arguments) { diff --git a/LightweightIocContainer/Registrations/DefaultRegistration.cs b/LightweightIocContainer/Registrations/DefaultRegistration.cs index 8b34300..b67b68f 100644 --- a/LightweightIocContainer/Registrations/DefaultRegistration.cs +++ b/LightweightIocContainer/Registrations/DefaultRegistration.cs @@ -46,7 +46,7 @@ namespace LightweightIocContainer.Registrations /// /// This action is invoked when an instance of this type is created. - /// Can be set in the by calling + /// Can be set in the by calling /// public Action OnCreateAction { get; private set; } diff --git a/LightweightIocContainer/Registrations/RegistrationFactory.cs b/LightweightIocContainer/Registrations/RegistrationFactory.cs index fd0b0b3..1bb72a2 100644 --- a/LightweightIocContainer/Registrations/RegistrationFactory.cs +++ b/LightweightIocContainer/Registrations/RegistrationFactory.cs @@ -8,7 +8,7 @@ using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations { /// - /// A factory to register interfaces and factories in an and create the needed s + /// A factory to register interfaces and factories in an and create the needed s /// public static class RegistrationFactory { @@ -28,9 +28,9 @@ namespace LightweightIocContainer.Registrations /// Register an Interface as an abstract typed factory and create a /// /// The abstract typed factory to register - /// The current + /// The current /// A new created with the given parameters - public static ITypedFactoryRegistration RegisterFactory(IInjectorContainer container) //TODO: Find a nicer way to inject the container into `TypedFactoryRegistration` + public static ITypedFactoryRegistration RegisterFactory(IIocContainer container) //TODO: Find a nicer way to inject the container into `TypedFactoryRegistration` { return new TypedFactoryRegistration(typeof(TFactory), container); } diff --git a/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs b/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs index 293996d..5bf24c1 100644 --- a/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs +++ b/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs @@ -20,9 +20,9 @@ namespace LightweightIocContainer.Registrations /// The type of the abstract typed factory public class TypedFactoryRegistration : ITypedFactoryRegistration { - private readonly IInjectorContainer _container; + private readonly IIocContainer _container; - public TypedFactoryRegistration(Type factoryType, IInjectorContainer container) + public TypedFactoryRegistration(Type factoryType, IIocContainer container) { _container = container; @@ -69,11 +69,11 @@ namespace LightweightIocContainer.Registrations typeBuilder.AddInterfaceImplementation(InterfaceType); - //add `private readonly IInjectorContainer _container` field - FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IInjectorContainer), FieldAttributes.Private | FieldAttributes.InitOnly); + //add `private readonly IIocContainer _container` field + FieldBuilder containerFieldBuilder = typeBuilder.DefineField("_container", typeof(IIocContainer), FieldAttributes.Private | FieldAttributes.InitOnly); //add ctor - ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IInjectorContainer)}); + ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] {typeof(IIocContainer)}); var constructorGenerator = constructorBuilder.GetILGenerator(); constructorGenerator.Emit(OpCodes.Ldarg_0); constructorGenerator.Emit(OpCodes.Ldarg_1); @@ -85,7 +85,7 @@ namespace LightweightIocContainer.Registrations //create a method that looks like this //public `createMethod.ReturnType` Create(`createMethod.GetParameters()`) //{ - // return IInjectorContainer.Resolve(`createMethod.ReturnType`, params); + // return IIocContainer.Resolve(`createMethod.ReturnType`, params); //} var args = createMethod.GetParameters(); @@ -122,7 +122,7 @@ namespace LightweightIocContainer.Registrations generator.EmitCall(OpCodes.Call, emptyArray, null); } - generator.EmitCall(OpCodes.Callvirt, typeof(IInjectorContainer).GetMethod(nameof(IInjectorContainer.Resolve), new[] { typeof(Type), typeof(object[])}), null); + generator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.Resolve), new[] { typeof(Type), typeof(object[])}), null); generator.Emit(OpCodes.Castclass, createMethod.ReturnType); generator.Emit(OpCodes.Ret); } diff --git a/Test.LightweightIocContainer/InjectorContainerTest.cs b/Test.LightweightIocContainer/InjectorContainerTest.cs deleted file mode 100644 index 1826951..0000000 --- a/Test.LightweightIocContainer/InjectorContainerTest.cs +++ /dev/null @@ -1,189 +0,0 @@ -using LightweightIocContainer; -using LightweightIocContainer.Exceptions; -using LightweightIocContainer.Interfaces; -using LightweightIocContainer.Registrations; -using Moq; -using NUnit.Framework; - -namespace Test.LightweightIocContainer -{ - [TestFixture] - public class InjectorContainerTest - { - #region TestClasses - //some of the test classes have to be public to allow the implementation of the factory - - public interface ITest - { - - } - - public interface ITestFactory - { - ITest Create(); - ITest Create(string name); - } - - private class Test : ITest - { - - } - - private class TestConstructor : ITest - { - public TestConstructor(string name, Test test) - { - - } - } - - #endregion - - - [Test] - public void TestInstall() - { - Mock installerMock = new Mock(); - - IInjectorContainer injectorContainer = new InjectorContainer(); - IInjectorContainer returnedContainer = injectorContainer.Install(installerMock.Object); - - installerMock.Verify(m => m.Install(It.IsAny()), Times.Once); - - Assert.AreEqual(injectorContainer, returnedContainer); - } - - [Test] - public void TestInstallMultiple() - { - Mock installer1Mock = new Mock(); - Mock installer2Mock = new Mock(); - Mock installer3Mock = new Mock(); - - IInjectorContainer injectorContainer = new InjectorContainer(); - IInjectorContainer returnedContainer = injectorContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object); - - installer1Mock.Verify(m => m.Install(It.IsAny()), Times.Once); - installer2Mock.Verify(m => m.Install(It.IsAny()), Times.Once); - installer3Mock.Verify(m => m.Install(It.IsAny()), Times.Once); - - Assert.AreEqual(injectorContainer, returnedContainer); - } - - [Test] - public void TestResolveNotRegistered() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - - Assert.Throws(() => injectorContainer.Resolve()); - } - - [Test] - public void TestResolve() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - - ITest resolvedTest = injectorContainer.Resolve(); - - Assert.IsInstanceOf(resolvedTest); - } - - [Test] - public void TestResolveWithParams() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - - ITest resolvedTest = injectorContainer.Resolve("Test", new Test()); - - Assert.IsInstanceOf(resolvedTest); - } - - [Test] - public void TestResolveWithMissingParam() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - injectorContainer.Register(RegistrationFactory.Register()); //this registration is abnormal and should only be used in unit tests - - ITest resolvedTest = injectorContainer.Resolve("Test"); - - Assert.IsInstanceOf(resolvedTest); - } - - [Test] - public void TestResolveReflection() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - - object resolvedTest = injectorContainer.Resolve(typeof(ITest), null); - - Assert.IsInstanceOf(resolvedTest); - } - - [Test] - public void TestResolveSingleton() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register(Lifestyle.Singleton)); - - ITest resolvedTest = injectorContainer.Resolve(); - ITest secondResolvedTest = injectorContainer.Resolve(); - - Assert.AreEqual(resolvedTest, secondResolvedTest); - } - - [Test] - public void TestResolveTransient() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - - ITest resolvedTest = injectorContainer.Resolve(); - ITest secondResolvedTest = injectorContainer.Resolve(); - - Assert.AreNotEqual(resolvedTest, secondResolvedTest); - } - - [Test] - public void TestResolveFactory() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - injectorContainer.Register(RegistrationFactory.RegisterFactory(injectorContainer)); - - ITestFactory testFactory = injectorContainer.Resolve(); - - Assert.IsInstanceOf(testFactory); - } - - [Test] - public void TestResolveFromFactory() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - injectorContainer.Register(RegistrationFactory.RegisterFactory(injectorContainer)); - - ITestFactory testFactory = injectorContainer.Resolve(); - ITest createdTest = testFactory.Create(); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveFromFactoryWithParams() - { - IInjectorContainer injectorContainer = new InjectorContainer(); - injectorContainer.Register(RegistrationFactory.Register()); - injectorContainer.Register(RegistrationFactory.Register()); //this registration is abnormal and should only be used in unit tests - injectorContainer.Register(RegistrationFactory.RegisterFactory(injectorContainer)); - - ITestFactory testFactory = injectorContainer.Resolve(); - ITest createdTest = testFactory.Create("Test"); - - Assert.IsInstanceOf(createdTest); - } - } -} \ No newline at end of file diff --git a/Test.LightweightIocContainer/IocContainerTest.cs b/Test.LightweightIocContainer/IocContainerTest.cs new file mode 100644 index 0000000..3a08a71 --- /dev/null +++ b/Test.LightweightIocContainer/IocContainerTest.cs @@ -0,0 +1,189 @@ +using LightweightIocContainer; +using LightweightIocContainer.Exceptions; +using LightweightIocContainer.Interfaces; +using LightweightIocContainer.Registrations; +using Moq; +using NUnit.Framework; + +namespace Test.LightweightIocContainer +{ + [TestFixture] + public class IocContainerTest + { + #region TestClasses + //some of the test classes have to be public to allow the implementation of the factory + + public interface ITest + { + + } + + public interface ITestFactory + { + ITest Create(); + ITest Create(string name); + } + + private class Test : ITest + { + + } + + private class TestConstructor : ITest + { + public TestConstructor(string name, Test test) + { + + } + } + + #endregion + + + [Test] + public void TestInstall() + { + Mock installerMock = new Mock(); + + IIocContainer iocContainer = new IocContainer(); + IIocContainer returnedContainer = iocContainer.Install(installerMock.Object); + + installerMock.Verify(m => m.Install(It.IsAny()), Times.Once); + + Assert.AreEqual(iocContainer, returnedContainer); + } + + [Test] + public void TestInstallMultiple() + { + Mock installer1Mock = new Mock(); + Mock installer2Mock = new Mock(); + Mock installer3Mock = new Mock(); + + IIocContainer iocContainer = new IocContainer(); + IIocContainer returnedContainer = iocContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object); + + installer1Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + installer2Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + installer3Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + + Assert.AreEqual(iocContainer, returnedContainer); + } + + [Test] + public void TestResolveNotRegistered() + { + IIocContainer iocContainer = new IocContainer(); + + Assert.Throws(() => iocContainer.Resolve()); + } + + [Test] + public void TestResolve() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + + ITest resolvedTest = iocContainer.Resolve(); + + Assert.IsInstanceOf(resolvedTest); + } + + [Test] + public void TestResolveWithParams() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + + ITest resolvedTest = iocContainer.Resolve("Test", new Test()); + + Assert.IsInstanceOf(resolvedTest); + } + + [Test] + public void TestResolveWithMissingParam() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + iocContainer.Register(RegistrationFactory.Register()); //this registration is abnormal and should only be used in unit tests + + ITest resolvedTest = iocContainer.Resolve("Test"); + + Assert.IsInstanceOf(resolvedTest); + } + + [Test] + public void TestResolveReflection() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + + object resolvedTest = iocContainer.Resolve(typeof(ITest), null); + + Assert.IsInstanceOf(resolvedTest); + } + + [Test] + public void TestResolveSingleton() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register(Lifestyle.Singleton)); + + ITest resolvedTest = iocContainer.Resolve(); + ITest secondResolvedTest = iocContainer.Resolve(); + + Assert.AreEqual(resolvedTest, secondResolvedTest); + } + + [Test] + public void TestResolveTransient() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + + ITest resolvedTest = iocContainer.Resolve(); + ITest secondResolvedTest = iocContainer.Resolve(); + + Assert.AreNotEqual(resolvedTest, secondResolvedTest); + } + + [Test] + public void TestResolveFactory() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + iocContainer.Register(RegistrationFactory.RegisterFactory(iocContainer)); + + ITestFactory testFactory = iocContainer.Resolve(); + + Assert.IsInstanceOf(testFactory); + } + + [Test] + public void TestResolveFromFactory() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + iocContainer.Register(RegistrationFactory.RegisterFactory(iocContainer)); + + ITestFactory testFactory = iocContainer.Resolve(); + ITest createdTest = testFactory.Create(); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveFromFactoryWithParams() + { + IIocContainer iocContainer = new IocContainer(); + iocContainer.Register(RegistrationFactory.Register()); + iocContainer.Register(RegistrationFactory.Register()); //this registration is abnormal and should only be used in unit tests + iocContainer.Register(RegistrationFactory.RegisterFactory(iocContainer)); + + ITestFactory testFactory = iocContainer.Resolve(); + ITest createdTest = testFactory.Create("Test"); + + Assert.IsInstanceOf(createdTest); + } + } +} \ No newline at end of file