From b18c0dc8588bb096a7fc745124207b8641a2ec3f Mon Sep 17 00:00:00 2001 From: Simon G Date: Wed, 1 Dec 2021 16:50:55 +0100 Subject: [PATCH] #50: append factory registration - add withFactory fluent interface - remove unneeded DefaultRegistration --- .../Factories/CustomTypedFactory.cs | 13 + .../Factories/TypedFactory.cs | 127 ++++++ .../Interfaces/Factories/ITypedFactory.cs | 7 +- .../Interfaces/IIocContainer.cs | 26 +- .../{FluentProviders => Fluent}/IOnCreate.cs | 6 +- .../Registrations/Fluent/IWithFactory.cs | 16 + .../IWithParameters.cs | 11 +- .../Registrations/IDefaultRegistration.cs | 18 - .../IMultipleMultitonRegistration.cs | 2 +- .../Registrations/IMultipleRegistration.cs | 10 +- .../Registrations/IMultitonRegistration.cs | 14 +- .../Registrations/IOpenGenericRegistration.cs | 9 +- .../Interfaces/Registrations/IRegistration.cs | 5 - .../Registrations/IRegistrationBase.cs | 16 +- .../Registrations/ISingleTypeRegistration.cs | 8 +- .../Registrations/ITypedRegistration.cs | 28 ++ .../Registrations/ITypedRegistrationBase.cs | 36 -- LightweightIocContainer/IocContainer.cs | 63 ++- .../LightweightIocContainer.xml | 366 +++++++----------- .../Registrations/DefaultRegistration.cs | 27 -- .../MultipleMultitonRegistration.cs | 14 +- .../Registrations/MultipleRegistration.cs | 124 +++--- .../Registrations/MultitonRegistration.cs | 8 +- .../Registrations/OpenGenericRegistration.cs | 30 +- .../Registrations/RegistrationBase.cs | 56 ++- .../Registrations/RegistrationFactory.cs | 29 +- .../Registrations/SingleTypeRegistration.cs | 21 +- .../Registrations/TypedFactoryRegistration.cs | 149 +------ ...gistrationBase.cs => TypedRegistration.cs} | 14 +- .../FluentFactoryRegistrationTest.cs | 230 +++++++++++ .../IocContainerTest.cs | 169 +------- Test.LightweightIocContainer/OnCreateTest.cs | 4 +- .../RegistrationBaseTest.cs | 13 +- .../SingleTypeRegistrationTest.cs | 2 +- 34 files changed, 800 insertions(+), 871 deletions(-) create mode 100644 LightweightIocContainer/Factories/CustomTypedFactory.cs rename LightweightIocContainer/Interfaces/Registrations/{FluentProviders => Fluent}/IOnCreate.cs (89%) create mode 100644 LightweightIocContainer/Interfaces/Registrations/Fluent/IWithFactory.cs rename LightweightIocContainer/Interfaces/Registrations/{FluentProviders => Fluent}/IWithParameters.cs (85%) delete mode 100644 LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs create mode 100644 LightweightIocContainer/Interfaces/Registrations/ITypedRegistration.cs delete mode 100644 LightweightIocContainer/Interfaces/Registrations/ITypedRegistrationBase.cs delete mode 100644 LightweightIocContainer/Registrations/DefaultRegistration.cs rename LightweightIocContainer/Registrations/{TypedRegistrationBase.cs => TypedRegistration.cs} (72%) create mode 100644 Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs diff --git a/LightweightIocContainer/Factories/CustomTypedFactory.cs b/LightweightIocContainer/Factories/CustomTypedFactory.cs new file mode 100644 index 0000000..1dd1ff5 --- /dev/null +++ b/LightweightIocContainer/Factories/CustomTypedFactory.cs @@ -0,0 +1,13 @@ +// Author: Gockner, Simon +// Created: 2021-12-01 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using LightweightIocContainer.Interfaces.Factories; + +namespace LightweightIocContainer.Factories +{ + public class CustomTypedFactory : ITypedFactory + { + + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Factories/TypedFactory.cs b/LightweightIocContainer/Factories/TypedFactory.cs index c452c33..05137b2 100644 --- a/LightweightIocContainer/Factories/TypedFactory.cs +++ b/LightweightIocContainer/Factories/TypedFactory.cs @@ -2,6 +2,13 @@ // Created: 2019-05-20 // Copyright(c) 2019 SimonG. All Rights Reserved. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using LightweightIocContainer.Exceptions; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Factories; namespace LightweightIocContainer.Factories @@ -12,9 +19,129 @@ namespace LightweightIocContainer.Factories /// The type of the abstract factory public class TypedFactory : ITypedFactory { + private const string CLEAR_MULTITON_INSTANCE_METHOD_NAME = "ClearMultitonInstance"; + + /// + /// The + /// + /// The current instance of the + public TypedFactory(IIocContainer container) => CreateFactory(container); + /// /// The implemented abstract typed factory/> /// public TFactory Factory { get; set; } + + /// + /// Creates the factory from the given abstract factory type + /// + /// Factory registration is invalid + /// Creation of abstract methods are illegal in their current state + private void CreateFactory(IIocContainer container) + { + Type factoryType = typeof(TFactory); + + List createMethods = factoryType.GetMethods().Where(m => m.ReturnType != typeof(void)).ToList(); + if (!createMethods.Any()) + throw new InvalidFactoryRegistrationException($"Factory {factoryType.Name} has no create methods."); + + AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run); + ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory"); + TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{factoryType.Name}"); + + typeBuilder.AddInterfaceImplementation(factoryType); + + //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(IIocContainer)}); + ILGenerator constructorGenerator = constructorBuilder.GetILGenerator(); + constructorGenerator.Emit(OpCodes.Ldarg_0); + constructorGenerator.Emit(OpCodes.Ldarg_1); + constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field + constructorGenerator.Emit(OpCodes.Ret); + + foreach (MethodInfo createMethod in createMethods) + { + //create a method that looks like this + //public `createMethod.ReturnType` Create(`createMethod.GetParameters()`) + //{ + // return IIocContainer.Resolve(`createMethod.ReturnType`, params); + //} + + ParameterInfo[] args = createMethod.GetParameters(); + + MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, + createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray()); + typeBuilder.DefineMethodOverride(methodBuilder, createMethod); + + ILGenerator generator = methodBuilder.GetILGenerator(); + + generator.Emit(OpCodes.Ldarg_0); + generator.Emit(OpCodes.Ldfld, containerFieldBuilder); + + if (args.Any()) + { + generator.Emit(OpCodes.Ldc_I4_S, args.Length); + generator.Emit(OpCodes.Newarr, typeof(object)); + + for (int i = 0; i < args.Length; i++) + { + generator.Emit(OpCodes.Dup); + generator.Emit(OpCodes.Ldc_I4_S, i); + generator.Emit(OpCodes.Ldarg_S, i + 1); + generator.Emit(OpCodes.Box, args[i].ParameterType); //Boxing is only needed for simple datatypes, but for now it is not a problem to box everything + generator.Emit(OpCodes.Stelem_Ref); + } + } + else + { + MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))?.MakeGenericMethod(typeof(object)); + generator.EmitCall(OpCodes.Call, emptyArray, null); + } + + generator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.Resolve), new[] { typeof(object[]) })?.MakeGenericMethod(createMethod.ReturnType), null); + generator.Emit(OpCodes.Castclass, createMethod.ReturnType); + generator.Emit(OpCodes.Ret); + } + + //if factory contains a method to clear multiton instances + MethodInfo multitonClearMethod = factoryType.GetMethods().FirstOrDefault(m => m.Name.Equals(CLEAR_MULTITON_INSTANCE_METHOD_NAME)); + if (multitonClearMethod != null) + { + //create a method that looks like this + //public void ClearMultitonInstance() + //{ + // IIocContainer.ClearMultitonInstances(); + //} + + if (multitonClearMethod.IsGenericMethod) + { + Type typeToClear = multitonClearMethod.GetGenericArguments().FirstOrDefault(); + if (typeToClear == null) + throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); + + MethodBuilder multitonClearMethodBuilder = typeBuilder.DefineMethod(multitonClearMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, + multitonClearMethod.ReturnType, null); + multitonClearMethodBuilder.DefineGenericParameters(typeToClear.Name); + + typeBuilder.DefineMethodOverride(multitonClearMethodBuilder, multitonClearMethod); + + ILGenerator multitonClearGenerator = multitonClearMethodBuilder.GetILGenerator(); + multitonClearGenerator.Emit(OpCodes.Ldarg_0); + multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder); + + multitonClearGenerator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.ClearMultitonInstances))?.MakeGenericMethod(typeToClear), null); + multitonClearGenerator.Emit(OpCodes.Ret); + } + else + { + throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); + } + } + + Factory = (TFactory) Activator.CreateInstance(typeBuilder.CreateTypeInfo().AsType(), container); + } } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Factories/ITypedFactory.cs b/LightweightIocContainer/Interfaces/Factories/ITypedFactory.cs index e229d26..2e318ef 100644 --- a/LightweightIocContainer/Interfaces/Factories/ITypedFactory.cs +++ b/LightweightIocContainer/Interfaces/Factories/ITypedFactory.cs @@ -4,11 +4,16 @@ namespace LightweightIocContainer.Interfaces.Factories { + public interface ITypedFactory + { + + } + /// /// Class to help implement an abstract typed factory /// /// The type of the abstract factory - public interface ITypedFactory + public interface ITypedFactory : ITypedFactory { /// /// The implemented abstract typed factory diff --git a/LightweightIocContainer/Interfaces/IIocContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs index efdb7ba..802184c 100644 --- a/LightweightIocContainer/Interfaces/IIocContainer.cs +++ b/LightweightIocContainer/Interfaces/IIocContainer.cs @@ -25,18 +25,19 @@ namespace LightweightIocContainer.Interfaces /// /// The Interface to register /// The Type that implements the interface - /// The for this + /// The for this /// The created - IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface; + ITypedRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface; /// /// Register an open generic Interface with an open generic Type that implements it /// /// The open generic Interface to register /// The open generic Type that implements the interface - /// The for this + /// The for this /// The created - IOpenGenericRegistration RegisterOpenGenerics(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient); + IOpenGenericRegistration RegisterOpenGenerics(Type tInterface, Type tImplementation, + Lifestyle lifestyle = Lifestyle.Transient); /// /// Register multiple interfaces for a that implements them @@ -44,7 +45,7 @@ namespace LightweightIocContainer.Interfaces /// The base interface to register /// A second interface to register /// The that implements both interfaces - /// The for this + /// The for this /// The created IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1; @@ -55,7 +56,7 @@ namespace LightweightIocContainer.Interfaces /// A second interface to register /// A third interface to register /// The that implements both interfaces - /// The for this + /// The for this /// The created IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface3, TInterface2, TInterface1; @@ -67,7 +68,7 @@ namespace LightweightIocContainer.Interfaces /// A third interface to register /// A fourth interface to register /// The that implements both interfaces - /// The for this + /// The for this /// The created IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1; @@ -80,7 +81,7 @@ namespace LightweightIocContainer.Interfaces /// A fourth interface to register /// A fifth interface to register /// The that implements both interfaces - /// The for this + /// The for this /// The created IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1; @@ -88,7 +89,7 @@ namespace LightweightIocContainer.Interfaces /// Register a without an interface /// /// The to register - /// The for this + /// The for this /// The created ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient); @@ -111,13 +112,6 @@ namespace LightweightIocContainer.Interfaces /// The created IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2; - /// - /// Register an Interface as an abstract typed factory - /// - /// The abstract typed factory to register - /// The created - ITypedFactoryRegistration RegisterFactory(); - /// /// Gets an instance of the given /// diff --git a/LightweightIocContainer/Interfaces/Registrations/FluentProviders/IOnCreate.cs b/LightweightIocContainer/Interfaces/Registrations/Fluent/IOnCreate.cs similarity index 89% rename from LightweightIocContainer/Interfaces/Registrations/FluentProviders/IOnCreate.cs rename to LightweightIocContainer/Interfaces/Registrations/Fluent/IOnCreate.cs index 5569c12..110695e 100644 --- a/LightweightIocContainer/Interfaces/Registrations/FluentProviders/IOnCreate.cs +++ b/LightweightIocContainer/Interfaces/Registrations/Fluent/IOnCreate.cs @@ -5,7 +5,7 @@ using System; using LightweightIocContainer.Interfaces.Installers; -namespace LightweightIocContainer.Interfaces.Registrations.FluentProviders +namespace LightweightIocContainer.Interfaces.Registrations.Fluent { /// /// Provides an to the generic @@ -30,7 +30,7 @@ namespace LightweightIocContainer.Interfaces.Registrations.FluentProviders /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - ITypedRegistrationBase OnCreate(Action action); + /// The current instance of this + ITypedRegistration OnCreate(Action action); } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithFactory.cs b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithFactory.cs new file mode 100644 index 0000000..9fb860a --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithFactory.cs @@ -0,0 +1,16 @@ +// Author: Gockner, Simon +// Created: 2021-11-30 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using LightweightIocContainer.Interfaces.Factories; + +namespace LightweightIocContainer.Interfaces.Registrations.Fluent +{ + public interface IWithFactory + { + ITypedFactory Factory { get; } + + IRegistrationBase WithFactory(); + IRegistrationBase WithFactory() where TFactoryImplementation : TFactoryInterface; + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/FluentProviders/IWithParameters.cs b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithParameters.cs similarity index 85% rename from LightweightIocContainer/Interfaces/Registrations/FluentProviders/IWithParameters.cs rename to LightweightIocContainer/Interfaces/Registrations/Fluent/IWithParameters.cs index 0bb2a9e..ccb2f46 100644 --- a/LightweightIocContainer/Interfaces/Registrations/FluentProviders/IWithParameters.cs +++ b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithParameters.cs @@ -6,13 +6,12 @@ using System; using LightweightIocContainer.Exceptions; using LightweightIocContainer.Interfaces.Installers; -namespace LightweightIocContainer.Interfaces.Registrations.FluentProviders +namespace LightweightIocContainer.Interfaces.Registrations.Fluent { /// - /// Provides a method to an + /// Provides a method to an /// - /// The registered interface - public interface IWithParameters + public interface IWithParameters { /// /// An of parameters that are used to an instance of this @@ -27,7 +26,7 @@ namespace LightweightIocContainer.Interfaces.Registrations.FluentProviders /// The parameters /// The current instance of this /// are already set or no parameters given - IRegistrationBase WithParameters(params object[] parameters); + IRegistrationBase WithParameters(params object[] parameters); /// /// Pass parameters that will be used to an instance of this @@ -36,6 +35,6 @@ namespace LightweightIocContainer.Interfaces.Registrations.FluentProviders /// The parameters with their position /// The current instance of this /// are already set or no parameters given - IRegistrationBase WithParameters(params (int index, object parameter)[] parameters); + IRegistrationBase WithParameters(params (int index, object parameter)[] parameters); } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs deleted file mode 100644 index a3f113d..0000000 --- a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Author: Gockner, Simon -// Created: 2019-11-22 -// Copyright(c) 2019 SimonG. All Rights Reserved. - -using System; - -namespace LightweightIocContainer.Interfaces.Registrations -{ - /// - /// The to register a for the Interface it implements - /// - /// The of the interface - /// The of the implementation - public interface IDefaultRegistration : ITypedRegistrationBase where TImplementation : TInterface - { - - } -} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs index 079248d..7869d02 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IMultipleMultitonRegistration.cs @@ -5,7 +5,7 @@ namespace LightweightIocContainer.Interfaces.Registrations { /// - /// An to register multiple interfaces for on implementation type that implements them as a multiton + /// An to register multiple interfaces for on implementation type that implements them as a multiton /// /// The first interface /// The second interface diff --git a/LightweightIocContainer/Interfaces/Registrations/IMultipleRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IMultipleRegistration.cs index b234b12..1f2aeec 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IMultipleRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IMultipleRegistration.cs @@ -11,7 +11,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// /// The first interface /// The implementation - public interface IMultipleRegistration : ITypedRegistrationBase where TImplementation : TInterface1 + public interface IMultipleRegistration : ITypedRegistration where TImplementation : TInterface1 { /// /// A of s that are registered within this @@ -20,7 +20,7 @@ namespace LightweightIocContainer.Interfaces.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -31,7 +31,7 @@ namespace LightweightIocContainer.Interfaces.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -43,7 +43,7 @@ namespace LightweightIocContainer.Interfaces.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -56,7 +56,7 @@ namespace LightweightIocContainer.Interfaces.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface diff --git a/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs index 5b20f0e..44c6650 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IMultitonRegistration.cs @@ -7,17 +7,9 @@ using System; namespace LightweightIocContainer.Interfaces.Registrations { /// - /// Non generic + /// Non generic /// - public interface IMultitonRegistration - { - - } - - /// - /// A base without implementation - /// - public interface IMultitonRegistration : ITypedRegistrationBase, IMultitonRegistration + public interface IMultitonRegistration : ITypedRegistration { /// /// The of the multiton scope @@ -30,7 +22,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// /// The registered interface /// The registered implementation - public interface IMultitonRegistration : IMultitonRegistration, IDefaultRegistration where TImplementation : TInterface + public interface IMultitonRegistration : IMultitonRegistration, ITypedRegistration where TImplementation : TInterface { } diff --git a/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs index 4aaebc4..9428dba 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IOpenGenericRegistration.cs @@ -2,18 +2,13 @@ // Created: 2020-09-18 // Copyright(c) 2020 SimonG. All Rights Reserved. -using System; - namespace LightweightIocContainer.Interfaces.Registrations { /// /// for open generic types /// - public interface IOpenGenericRegistration : IRegistration, ILifestyleProvider + public interface IOpenGenericRegistration : ITypedRegistration { - /// - /// The that implements the that is registered with this - /// - Type ImplementationType { get; } + } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs index 65d6dd6..019c7fb 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs @@ -11,11 +11,6 @@ namespace LightweightIocContainer.Interfaces.Registrations /// public interface IRegistration { - /// - /// The name of the - /// - string Name { get; } - /// /// The of the Interface that is registered with this /// diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs index e8ba70e..780b70c 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs @@ -2,23 +2,11 @@ // Created: 2019-05-20 // Copyright(c) 2019 SimonG. All Rights Reserved. -using LightweightIocContainer.Interfaces.Registrations.FluentProviders; +using LightweightIocContainer.Interfaces.Registrations.Fluent; namespace LightweightIocContainer.Interfaces.Registrations { - /// - /// A base without generic interface - /// - public interface IRegistrationBase : IRegistration, ILifestyleProvider - { - - } - - /// - /// The that is used to register an Interface - /// - /// The registered Interface - public interface IRegistrationBase : IRegistrationBase, IWithParameters + public interface IRegistrationBase : IRegistration, IWithFactory, IWithParameters, ILifestyleProvider { } diff --git a/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs index ad9f188..c0818dd 100644 --- a/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs +++ b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs @@ -7,10 +7,10 @@ using System; namespace LightweightIocContainer.Interfaces.Registrations { /// - /// The to register either only an interface or only a + /// The to register either only an interface or only a /// - /// The of the - public interface ISingleTypeRegistration : IRegistrationBase + /// The of the + public interface ISingleTypeRegistration : IRegistrationBase { /// /// that is invoked instead of creating an instance of this the default way @@ -21,7 +21,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// Pass a that will be invoked instead of creating an instance of this the default way /// /// The - /// The current instance of this + /// The current instance of this ISingleTypeRegistration WithFactoryMethod(Func factoryMethod); } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/ITypedRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/ITypedRegistration.cs new file mode 100644 index 0000000..ef67b9c --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/ITypedRegistration.cs @@ -0,0 +1,28 @@ +// Author: Simon Gockner +// Created: 2019-12-08 +// Copyright(c) 2019 SimonG. All Rights Reserved. + +using System; +using LightweightIocContainer.Interfaces.Registrations.Fluent; + +namespace LightweightIocContainer.Interfaces.Registrations +{ + /// + /// A base without generic interface and implementation + /// + public interface ITypedRegistration : IRegistrationBase + { + /// + /// The that implements the that is registered with this + /// + Type ImplementationType { get; } + } + + /// + /// A that implements a + /// + public interface ITypedRegistration : ITypedRegistration, IOnCreate where TImplementation : TInterface + { + + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/ITypedRegistrationBase.cs b/LightweightIocContainer/Interfaces/Registrations/ITypedRegistrationBase.cs deleted file mode 100644 index e5752fa..0000000 --- a/LightweightIocContainer/Interfaces/Registrations/ITypedRegistrationBase.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Author: Simon Gockner -// Created: 2019-12-08 -// Copyright(c) 2019 SimonG. All Rights Reserved. - -using System; -using LightweightIocContainer.Interfaces.Registrations.FluentProviders; - -namespace LightweightIocContainer.Interfaces.Registrations -{ - /// - /// A base without generic interface and implementation - /// - public interface ITypedRegistrationBase : IRegistrationBase - { - /// - /// The that implements the that is registered with this - /// - Type ImplementationType { get; } - } - - /// - /// A base without generic implementation - /// - public interface ITypedRegistrationBase : IRegistrationBase, ITypedRegistrationBase - { - - } - - /// - /// A that implements a - /// - public interface ITypedRegistrationBase : ITypedRegistrationBase, IOnCreate where TImplementation : TInterface - { - - } -} \ No newline at end of file diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs index a01c073..2aec19d 100644 --- a/LightweightIocContainer/IocContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -10,9 +10,10 @@ using System.Runtime.CompilerServices; using JetBrains.Annotations; using LightweightIocContainer.Exceptions; using LightweightIocContainer.Interfaces; +using LightweightIocContainer.Interfaces.Factories; using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Registrations; -using LightweightIocContainer.Interfaces.Registrations.FluentProviders; +using LightweightIocContainer.Interfaces.Registrations.Fluent; using LightweightIocContainer.Registrations; namespace LightweightIocContainer @@ -56,9 +57,9 @@ namespace LightweightIocContainer /// The Type that implements the interface /// The for this /// The created - public IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface + public ITypedRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface { - IDefaultRegistration registration = _registrationFactory.Register(lifestyle); + ITypedRegistration registration = _registrationFactory.Register(lifestyle); Register(registration); return registration; @@ -210,13 +211,7 @@ namespace LightweightIocContainer /// /// The abstract typed factory to register /// The created - public ITypedFactoryRegistration RegisterFactory() - { - ITypedFactoryRegistration registration = _registrationFactory.RegisterFactory(); - Register(registration); - - return registration; - } + internal void RegisterFactory(ITypedFactory factory) => Register(_registrationFactory.RegisterFactory(factory)); /// /// Add the to the the @@ -255,7 +250,7 @@ namespace LightweightIocContainer /// /// The given /// An instance of the given - public T Resolve() => ResolveInternal(null); + public virtual T Resolve() => ResolveInternal(null); /// /// Gets an instance of the given @@ -305,8 +300,8 @@ namespace LightweightIocContainer { if (defaultRegistration.Lifestyle == Lifestyle.Singleton) resolvedInstance = GetOrCreateSingletonInstance(defaultRegistration, arguments, resolveStack); - else if (defaultRegistration is IMultitonRegistration multitonRegistration && defaultRegistration.Lifestyle == Lifestyle.Multiton) - resolvedInstance = GetOrCreateMultitonInstance(multitonRegistration, arguments, resolveStack); + else if (defaultRegistration is IMultitonRegistration multitonRegistration && defaultRegistration.Lifestyle == Lifestyle.Multiton) + resolvedInstance = GetOrCreateMultitonInstance(multitonRegistration, arguments, resolveStack); else resolvedInstance = CreateInstance(defaultRegistration, arguments, resolveStack); } @@ -314,13 +309,6 @@ namespace LightweightIocContainer { resolvedInstance = typedFactoryRegistration.Factory.Factory; } - else if (registration is IOpenGenericRegistration openGenericRegistration) - { - if (openGenericRegistration.Lifestyle == Lifestyle.Singleton) - resolvedInstance = GetOrCreateSingletonInstance(openGenericRegistration, arguments, resolveStack); - else - resolvedInstance = CreateInstance(openGenericRegistration, arguments, resolveStack); - } else throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}."); @@ -340,12 +328,10 @@ namespace LightweightIocContainer private T GetOrCreateSingletonInstance(IRegistration registration, object[] arguments, List resolveStack) { Type type; - if (registration is ITypedRegistrationBase typedRegistration) + if (registration is ITypedRegistration typedRegistration) type = typedRegistration.ImplementationType; else if (registration is ISingleTypeRegistration singleTypeRegistration) type = singleTypeRegistration.InterfaceType; - else if (registration is IOpenGenericRegistration openGenericRegistration) - type = openGenericRegistration.ImplementationType; else throw new UnknownRegistrationException($"There is no registration {registration.GetType().Name} that can have lifestyle singleton."); @@ -371,7 +357,7 @@ namespace LightweightIocContainer /// An existing or newly created multiton instance of the given /// No arguments given /// Scope argument not given - private T GetOrCreateMultitonInstance(IMultitonRegistration registration, object[] arguments, List resolveStack) + private T GetOrCreateMultitonInstance(IMultitonRegistration registration, object[] arguments, List resolveStack) { if (arguments == null || !arguments.Any()) throw new MultitonResolveException("Can not resolve multiton without arguments.", typeof(T)); @@ -413,11 +399,20 @@ namespace LightweightIocContainer /// A newly created instance of the given private T CreateInstance(IRegistration registration, object[] arguments, List resolveStack) { - if (registration is IWithParameters { Parameters: { } } registrationWithParameters) + if (registration is IWithParameters { Parameters: { } } registrationWithParameters) arguments = UpdateArgumentsWithRegistrationParameters(registrationWithParameters, arguments); T instance; - if (registration is ITypedRegistrationBase defaultRegistration) + if (registration is IOpenGenericRegistration openGenericRegistration) + { + arguments = ResolveConstructorArguments(openGenericRegistration.ImplementationType, arguments, resolveStack); + + //create generic implementation type from generic arguments of T + Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments); + + instance = (T) Activator.CreateInstance(genericImplementationType, arguments); + } + else if (registration is ITypedRegistration defaultRegistration) { arguments = ResolveConstructorArguments(defaultRegistration.ImplementationType, arguments, resolveStack); instance = (T) Activator.CreateInstance(defaultRegistration.ImplementationType, arguments); @@ -435,15 +430,6 @@ namespace LightweightIocContainer else //factory method set to create the instance instance = singleTypeRegistration.FactoryMethod(this); } - else if (registration is IOpenGenericRegistration openGenericRegistration) - { - arguments = ResolveConstructorArguments(openGenericRegistration.ImplementationType, arguments, resolveStack); - - //create generic implementation type from generic arguments of T - Type genericImplementationType = openGenericRegistration.ImplementationType.MakeGenericType(typeof(T).GenericTypeArguments); - - instance = (T) Activator.CreateInstance(genericImplementationType, arguments); - } else throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}."); @@ -456,11 +442,10 @@ namespace LightweightIocContainer /// /// Update the given arguments with the of the given /// - /// The given /// The of the given /// The constructor arguments /// The argument list updated with the - private object[] UpdateArgumentsWithRegistrationParameters(IWithParameters registration, object[] arguments) + private object[] UpdateArgumentsWithRegistrationParameters(IWithParameters registration, object[] arguments) { if (arguments != null && arguments.Any()) //if more arguments were passed to resolve { @@ -588,7 +573,7 @@ namespace LightweightIocContainer if (registration != null) return registration; - registration = _registrations.OfType().FirstOrDefault(r => r.ImplementationType == typeof(T)); + registration = _registrations.OfType().FirstOrDefault(r => r.ImplementationType == typeof(T)); if (registration != null) return registration; @@ -610,7 +595,7 @@ namespace LightweightIocContainer public void ClearMultitonInstances() { IRegistration registration = FindRegistration(); - if (!(registration is IMultitonRegistration multitonRegistration)) + if (!(registration is IMultitonRegistration multitonRegistration)) return; var multitonInstance = _multitons.FirstOrDefault(m => m.type == multitonRegistration.ImplementationType); diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml index 1123293..47e6289 100644 --- a/LightweightIocContainer/LightweightIocContainer.xml +++ b/LightweightIocContainer/LightweightIocContainer.xml @@ -280,11 +280,24 @@ The type of the abstract factory + + + The + + The current instance of the + The implemented abstract typed factory/> + + + Creates the factory from the given abstract factory type + + Factory registration is invalid + Creation of abstract methods are illegal in their current state + Helper class to call a generic method without generic type parameters @@ -372,7 +385,7 @@ The Interface to register The Type that implements the interface - The for this + The for this The created @@ -381,7 +394,7 @@ The open generic Interface to register The open generic Type that implements the interface - The for this + The for this The created @@ -391,7 +404,7 @@ The base interface to register A second interface to register The that implements both interfaces - The for this + The for this The created @@ -402,7 +415,7 @@ A second interface to register A third interface to register The that implements both interfaces - The for this + The for this The created @@ -414,7 +427,7 @@ A third interface to register A fourth interface to register The that implements both interfaces - The for this + The for this The created @@ -427,7 +440,7 @@ A fourth interface to register A fifth interface to register The that implements both interfaces - The for this + The for this The created @@ -435,7 +448,7 @@ Register a without an interface The to register - The for this + The for this The created @@ -457,13 +470,6 @@ The Type of the multiton scope The created - - - Register an Interface as an abstract typed factory - - The abstract typed factory to register - The created - Gets an instance of the given @@ -513,67 +519,59 @@ The current - + - Provides an to the generic + Provides an to the generic - + This is invoked when an instance of this type is created. - Can be set in the by calling + Can be set in the by calling - + - Provides an method to an + Provides an method to an The registered interface The registered implementation - + Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this - + - Provides a method to an + Provides a method to an - The registered interface - + An of parameters that are used to an instance of this - Can be set in the by calling + Can be set in the by calling - + Pass parameters that will be used to an instance of this Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving The parameters - The current instance of this - are already set or no parameters given + The current instance of this + are already set or no parameters given - + Pass parameters that will be used to an instance of this Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving The parameters with their position - The current instance of this - are already set or no parameters given - - - - The to register a for the Interface it implements - - The of the interface - The of the implementation + The current instance of this + are already set or no parameters given @@ -587,7 +585,7 @@ - An to register multiple interfaces for on implementation type that implements them as a multiton + An to register multiple interfaces for on implementation type that implements them as a multiton The first interface The second interface @@ -607,7 +605,7 @@ - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -615,7 +613,7 @@ - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -624,7 +622,7 @@ - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -634,7 +632,7 @@ - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -645,15 +643,10 @@ - Non generic + Non generic - - - A base without implementation - - - + The of the multiton scope @@ -670,42 +663,21 @@ for open generic types - - - The that implements the that is registered with this - - The base registration that is used to register an Interface - - - The name of the - - The of the Interface that is registered with this - - - A base without generic interface - - - - - The that is used to register an Interface - - The registered Interface - - The to register either only an interface or only a + The to register either only an interface or only a - The of the + The of the @@ -717,7 +689,7 @@ Pass a that will be invoked instead of creating an instance of this the default way The - The current instance of this + The current instance of this @@ -730,24 +702,19 @@ The class that contains the implemented abstract factory of this - + - A base without generic interface and implementation + A base without generic interface and implementation - + - The that implements the that is registered with this + The that implements the that is registered with this - + - A base without generic implementation - - - - - A that implements a + A that implements a @@ -778,7 +745,7 @@ The Interface to register The Type that implements the interface - The for this + The for this The created @@ -799,7 +766,7 @@ The base interface to register A second interface to register The that implements both interfaces - The for this + The for this The created @@ -810,7 +777,7 @@ A second interface to register A third interface to register The that implements both interfaces - The for this + The for this The created @@ -822,7 +789,7 @@ A third interface to register A fourth interface to register The that implements both interfaces - The for this + The for this The created @@ -835,7 +802,7 @@ A fourth interface to register A fifth interface to register The that implements both interfaces - The for this + The for this The created @@ -843,7 +810,7 @@ Register a without an interface The to register - The for this + The for this The created @@ -865,7 +832,7 @@ The Type of the multiton scope The created - + Register an Interface as an abstract typed factory @@ -933,7 +900,7 @@ The current resolve stack An existing or newly created singleton instance of the given - + Gets or creates a multiton instance of a given @@ -955,14 +922,13 @@ The current resolve stack A newly created instance of the given - + - Update the given arguments with the of the given + Update the given arguments with the of the given - The given - The of the given + The of the given The constructor arguments - The argument list updated with the + The argument list updated with the @@ -994,7 +960,7 @@ - The Lifestyles that can be used for a + The Lifestyles that can be used for a @@ -1012,37 +978,23 @@ A new instance gets created if the given scope has no created instance yet. Otherwise the already created instance is used. - - - The to register a for the Interface it implements - - The of the interface - The of the implementation - - - - The to register a for the Interface it implements - - The of the interface - The of the implementation - The of the - - An to register multiple interfaces for on implementation type that implements them as a multiton + An to register multiple interfaces for on implementation type that implements them as a multiton The first interface The second interface The implementation - + - An to register multiple interfaces for on implementation type that implements them as a multiton + An to register multiple interfaces for on implementation type that implements them as a multiton The of the first interface The of the second interface The of the implementation The of the multiton scope + The current instance of the @@ -1054,7 +1006,7 @@ Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this @@ -1063,13 +1015,14 @@ The first interface The implementation - + The base class for every to register multiple interfaces The of the first interface The of the implementation The of this + The current instance of the @@ -1078,57 +1031,59 @@ - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface The implementation - + - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The of the first interface The of the second interface The of the implementation The of this + The current instance of the Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface The third interface The implementation - + - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The of the first interface The of the second interface The of the third interface The of the implementation The of this + The current instance of the Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -1136,9 +1091,9 @@ The fourth interface The implementation - + - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The of the first interface The of the second interface @@ -1146,17 +1101,18 @@ The of the fourth interface The of the implementation The of this + The current instance of the Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The first interface The second interface @@ -1165,9 +1121,9 @@ The fifth interface The implementation - + - An to register multiple interfaces for on implementation type + An to register multiple interfaces for on implementation type The of the first interface The of the second interface @@ -1176,13 +1132,14 @@ The of the fifth interface The of the implementation The of this + The current instance of the Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this @@ -1191,13 +1148,14 @@ The registered interface The registered implementation - + The registration that is used to register a multiton The of the Interface The of the Implementation The of the Multiton Scope + The current instance of the @@ -1209,85 +1167,66 @@ for open generic types - + for open generic types The of the interface The of the implementation type - The of this - - - - The name of the - - - - - The of the Interface that is registered with this - + The of this + The current instance of the The that implements the that is registered with this - + - The Lifestyle of Instances that are created with this - - - - - The that is used to register an Interface + The that is used to register an Interface - The registered Interface - + - The that is used to register an Interface + The that is used to register an Interface The of the Interface The of the registration + The current instance of the - - - The name of the - - - + - The of the Interface that is registered with this + The of the Interface that is registered with this - + - The of Instances that are created with this + The of Instances that are created with this - + An of parameters that are used to an instance of this - Can be set in the by calling + Can be set in the by calling - + - Pass parameters that will be used to an instance of this + Pass parameters that will be used to an instance of this Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving The parameters - The current instance of this - are already set or no parameters given + The current instance of this + are already set or no parameters given - + Pass parameters that will be used to an instance of this Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving The parameters with their position - The current instance of this - are already set or no parameters given + The current instance of this + are already set or no parameters given @@ -1296,12 +1235,12 @@ - Register an Interface with a Type that implements it and create a + Register an Interface with a Type that implements it and create a The Interface to register The Type that implements the interface - The for this - A new created with the given parameters + The for this + A new created with the given parameters @@ -1319,7 +1258,7 @@ The base interface to register A second interface to register The that implements both interfaces - The for this + The for this The created @@ -1330,7 +1269,7 @@ A second interface to register A third interface to register The that implements both interfaces - The for this + The for this The created @@ -1342,7 +1281,7 @@ A third interface to register A fourth interface to register The that implements both interfaces - The for this + The for this The created @@ -1355,7 +1294,7 @@ A fourth interface to register A fifth interface to register The that implements both interfaces - The for this + The for this The created @@ -1385,7 +1324,7 @@ The Type of the multiton scope A new created with the given parameters - + Register an Interface as an abstract typed factory and create a @@ -1394,16 +1333,17 @@ - The to register either only an interface or only a + The to register either only an interface or only a - The of the + The of the - + - The to register either only an interface or only a + The to register either only an interface or only a The of the interface or - The of the + The of the + The current instance of the @@ -1415,7 +1355,7 @@ Pass a that will be invoked instead of creating an instance of this the default way The - The current instance of this + The current instance of this @@ -1423,21 +1363,15 @@ The of the abstract typed factory - + The registration that is used to register an abstract typed factory - The of the abstract typed factory - The current instance of the - - - - The name of the - + The for this - The of the abstract typed factory that is registered with this + The of the factory that is registered with this @@ -1445,43 +1379,37 @@ The class that contains the implemented abstract factory of this - - - Creates the factory from the given abstract factory type - - Factory registration is invalid - Creation of abstract methods are illegal in their current state - - + - A that implements a + A that implements a - + - A that implements a + A that implements a The of the interface The of the implementation type - The of this + The of this + The current instance of the - + - The that implements the that is registered with this + The that implements the that is registered with this - + This is invoked when an instance of this type is created. - Can be set in the by calling + Can be set in the by calling - + Pass an that will be invoked when an instance of this type is created The - The current instance of this + The current instance of this diff --git a/LightweightIocContainer/Registrations/DefaultRegistration.cs b/LightweightIocContainer/Registrations/DefaultRegistration.cs deleted file mode 100644 index 0b4917f..0000000 --- a/LightweightIocContainer/Registrations/DefaultRegistration.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Author: Gockner, Simon -// Created: 2019-11-22 -// Copyright(c) 2019 SimonG. All Rights Reserved. - -using System; -using LightweightIocContainer.Interfaces.Registrations; - -namespace LightweightIocContainer.Registrations -{ - /// - /// The to register a for the Interface it implements - /// - /// The of the interface - /// The of the implementation - public class DefaultRegistration : TypedRegistrationBase, IDefaultRegistration where TImplementation : TInterface - { - /// - /// The to register a for the Interface it implements - /// - /// The of the interface - /// The of the implementation - /// The of the - public DefaultRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle) - : base(interfaceType, implementationType, lifestyle) => - Name = $"{InterfaceType.Name}, {ImplementationType.Name}, Lifestyle: {Lifestyle.ToString()}"; - } -} \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs index d2ce510..3a3e61f 100644 --- a/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs +++ b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations @@ -23,13 +24,14 @@ namespace LightweightIocContainer.Registrations /// The of the second interface /// The of the implementation /// The of the multiton scope - public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope) - : base(interfaceType1, implementationType, scope) + /// The current instance of the + public MultipleMultitonRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Type scope, IocContainer container) + : base(interfaceType1, implementationType, scope, container) { Registrations = new List() { - new MultitonRegistration(interfaceType1, implementationType, scope), - new MultitonRegistration(interfaceType2, implementationType, scope) + new MultitonRegistration(interfaceType1, implementationType, scope, container), + new MultitonRegistration(interfaceType2, implementationType, scope, container) }; } @@ -42,8 +44,8 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public override ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public override ITypedRegistration OnCreate(Action action) { foreach (var registration in Registrations) { diff --git a/LightweightIocContainer/Registrations/MultipleRegistration.cs b/LightweightIocContainer/Registrations/MultipleRegistration.cs index bfb6c6c..002ee0e 100644 --- a/LightweightIocContainer/Registrations/MultipleRegistration.cs +++ b/LightweightIocContainer/Registrations/MultipleRegistration.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations @@ -13,7 +14,7 @@ namespace LightweightIocContainer.Registrations /// /// The first interface /// The implementation - public abstract class MultipleRegistration : TypedRegistrationBase, IMultipleRegistration where TImplementation : TInterface1 + public abstract class MultipleRegistration : TypedRegistration, IMultipleRegistration where TImplementation : TInterface1 { /// /// The base class for every to register multiple interfaces @@ -21,8 +22,9 @@ namespace LightweightIocContainer.Registrations /// The of the first interface /// The of the implementation /// The of this - protected MultipleRegistration(Type interfaceType1, Type implementationType, Lifestyle lifestyle) - : base(interfaceType1, implementationType, lifestyle) + /// The current instance of the + protected MultipleRegistration(Type interfaceType1, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType1, implementationType, lifestyle, container) { } @@ -34,7 +36,7 @@ namespace LightweightIocContainer.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -42,19 +44,20 @@ namespace LightweightIocContainer.Registrations public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface1, TInterface2 { /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The of the first interface /// The of the second interface /// The of the implementation /// The of this - public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Lifestyle lifestyle) - : base(interfaceType1, implementationType, lifestyle) + /// The current instance of the + public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType1, implementationType, lifestyle, container) { - Registrations = new List() + Registrations = new List { - new DefaultRegistration(interfaceType1, implementationType, lifestyle), - new DefaultRegistration(interfaceType2, implementationType, lifestyle) + new TypedRegistration(interfaceType1, implementationType, lifestyle, container), + new TypedRegistration(interfaceType2, implementationType, lifestyle, container) }; } @@ -62,14 +65,14 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public override ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public override ITypedRegistration OnCreate(Action action) { foreach (var registration in Registrations) { - if (registration is IDefaultRegistration interface2Registration) + if (registration is ITypedRegistration interface2Registration) interface2Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface1Registration) + else if (registration is ITypedRegistration interface1Registration) interface1Registration.OnCreate(action); } @@ -78,7 +81,7 @@ namespace LightweightIocContainer.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -87,21 +90,22 @@ namespace LightweightIocContainer.Registrations public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface3, TInterface2, TInterface1 { /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The of the first interface /// The of the second interface /// The of the third interface /// The of the implementation /// The of this - public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type implementationType, Lifestyle lifestyle) - : base(interfaceType1, implementationType, lifestyle) + /// The current instance of the + public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType1, implementationType, lifestyle, container) { - Registrations = new List() + Registrations = new List { - new DefaultRegistration(interfaceType1, implementationType, lifestyle), - new DefaultRegistration(interfaceType2, implementationType, lifestyle), - new DefaultRegistration(interfaceType3, implementationType, lifestyle) + new TypedRegistration(interfaceType1, implementationType, lifestyle, container), + new TypedRegistration(interfaceType2, implementationType, lifestyle, container), + new TypedRegistration(interfaceType3, implementationType, lifestyle, container) }; } @@ -109,16 +113,16 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public override ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public override ITypedRegistration OnCreate(Action action) { foreach (var registration in Registrations) { - if (registration is IDefaultRegistration interface3Registration) + if (registration is ITypedRegistration interface3Registration) interface3Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface2Registration) + else if (registration is ITypedRegistration interface2Registration) interface2Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface1Registration) + else if (registration is ITypedRegistration interface1Registration) interface1Registration.OnCreate(action); } @@ -127,7 +131,7 @@ namespace LightweightIocContainer.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -137,7 +141,7 @@ namespace LightweightIocContainer.Registrations public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1 { /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The of the first interface /// The of the second interface @@ -145,15 +149,16 @@ namespace LightweightIocContainer.Registrations /// The of the fourth interface /// The of the implementation /// The of this - public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type implementationType, Lifestyle lifestyle) - : base(interfaceType1, implementationType, lifestyle) + /// The current instance of the + public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType1, implementationType, lifestyle, container) { - Registrations = new List() + Registrations = new List { - new DefaultRegistration(interfaceType1, implementationType, lifestyle), - new DefaultRegistration(interfaceType2, implementationType, lifestyle), - new DefaultRegistration(interfaceType3, implementationType, lifestyle), - new DefaultRegistration(interfaceType4, implementationType, lifestyle) + new TypedRegistration(interfaceType1, implementationType, lifestyle, container), + new TypedRegistration(interfaceType2, implementationType, lifestyle, container), + new TypedRegistration(interfaceType3, implementationType, lifestyle, container), + new TypedRegistration(interfaceType4, implementationType, lifestyle, container) }; } @@ -161,18 +166,18 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public override ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public override ITypedRegistration OnCreate(Action action) { foreach (var registration in Registrations) { - if (registration is IDefaultRegistration interface4Registration) + if (registration is ITypedRegistration interface4Registration) interface4Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface3Registration) + else if (registration is ITypedRegistration interface3Registration) interface3Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface2Registration) + else if (registration is ITypedRegistration interface2Registration) interface2Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface1Registration) + else if (registration is ITypedRegistration interface1Registration) interface1Registration.OnCreate(action); } @@ -181,7 +186,7 @@ namespace LightweightIocContainer.Registrations } /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The first interface /// The second interface @@ -192,7 +197,7 @@ namespace LightweightIocContainer.Registrations public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1 { /// - /// An to register multiple interfaces for on implementation type + /// An to register multiple interfaces for on implementation type /// /// The of the first interface /// The of the second interface @@ -201,16 +206,17 @@ namespace LightweightIocContainer.Registrations /// The of the fifth interface /// The of the implementation /// The of this - public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type interfaceType5, Type implementationType, Lifestyle lifestyle) - : base(interfaceType1, implementationType, lifestyle) + /// The current instance of the + public MultipleRegistration(Type interfaceType1, Type interfaceType2, Type interfaceType3, Type interfaceType4, Type interfaceType5, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType1, implementationType, lifestyle, container) { - Registrations = new List() + Registrations = new List { - new DefaultRegistration(interfaceType1, implementationType, lifestyle), - new DefaultRegistration(interfaceType2, implementationType, lifestyle), - new DefaultRegistration(interfaceType3, implementationType, lifestyle), - new DefaultRegistration(interfaceType4, implementationType, lifestyle), - new DefaultRegistration(interfaceType5, implementationType, lifestyle) + new TypedRegistration(interfaceType1, implementationType, lifestyle, container), + new TypedRegistration(interfaceType2, implementationType, lifestyle, container), + new TypedRegistration(interfaceType3, implementationType, lifestyle, container), + new TypedRegistration(interfaceType4, implementationType, lifestyle, container), + new TypedRegistration(interfaceType5, implementationType, lifestyle, container) }; } @@ -218,20 +224,20 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public override ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public override ITypedRegistration OnCreate(Action action) { foreach (var registration in Registrations) { - if (registration is IDefaultRegistration interface5Registration) + if (registration is ITypedRegistration interface5Registration) interface5Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface4Registration) + else if (registration is ITypedRegistration interface4Registration) interface4Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface3Registration) + else if (registration is ITypedRegistration interface3Registration) interface3Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface2Registration) + else if (registration is ITypedRegistration interface2Registration) interface2Registration.OnCreate(action); - else if (registration is IDefaultRegistration interface1Registration) + else if (registration is ITypedRegistration interface1Registration) interface1Registration.OnCreate(action); } diff --git a/LightweightIocContainer/Registrations/MultitonRegistration.cs b/LightweightIocContainer/Registrations/MultitonRegistration.cs index e49130b..b2b7154 100644 --- a/LightweightIocContainer/Registrations/MultitonRegistration.cs +++ b/LightweightIocContainer/Registrations/MultitonRegistration.cs @@ -3,6 +3,7 @@ // Copyright(c) 2019 SimonG. All Rights Reserved. using System; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations @@ -12,7 +13,7 @@ namespace LightweightIocContainer.Registrations /// /// The registered interface /// The registered implementation - public class MultitonRegistration : DefaultRegistration, IMultitonRegistration where TImplementation : TInterface + public class MultitonRegistration : TypedRegistration, IMultitonRegistration where TImplementation : TInterface { /// /// The registration that is used to register a multiton @@ -20,8 +21,9 @@ namespace LightweightIocContainer.Registrations /// The of the Interface /// The of the Implementation /// The of the Multiton Scope - public MultitonRegistration(Type interfaceType, Type implementationType, Type scope) - : base(interfaceType, implementationType, Lifestyle.Multiton) => + /// The current instance of the + public MultitonRegistration(Type interfaceType, Type implementationType, Type scope, IocContainer container) + : base(interfaceType, implementationType, Lifestyle.Multiton, container) => Scope = scope; /// diff --git a/LightweightIocContainer/Registrations/OpenGenericRegistration.cs b/LightweightIocContainer/Registrations/OpenGenericRegistration.cs index df37b4f..458233a 100644 --- a/LightweightIocContainer/Registrations/OpenGenericRegistration.cs +++ b/LightweightIocContainer/Registrations/OpenGenericRegistration.cs @@ -3,6 +3,7 @@ // Copyright(c) 2020 SimonG. All Rights Reserved. using System; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations @@ -10,7 +11,7 @@ namespace LightweightIocContainer.Registrations /// /// for open generic types /// - public class OpenGenericRegistration : IOpenGenericRegistration + public class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistration { /// /// for open generic types @@ -18,33 +19,14 @@ namespace LightweightIocContainer.Registrations /// The of the interface /// The of the implementation type /// The of this - public OpenGenericRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle) - { - InterfaceType = interfaceType; + /// The current instance of the + public OpenGenericRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer iocContainer) + : base(interfaceType, lifestyle, iocContainer) => ImplementationType = implementationType; - Lifestyle = lifestyle; - - Name = $"{InterfaceType.Name}, {ImplementationType.Name}, Lifestyle: {Lifestyle.ToString()}"; - } - - /// - /// The name of the - /// - public string Name { get; } - - /// - /// The of the Interface that is registered with this - /// - public Type InterfaceType { get; } - + /// /// The that implements the that is registered with this /// public Type ImplementationType { get; } - - /// - /// The Lifestyle of Instances that are created with this - /// - public Lifestyle Lifestyle { get; } } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/RegistrationBase.cs b/LightweightIocContainer/Registrations/RegistrationBase.cs index 8e0f617..0998978 100644 --- a/LightweightIocContainer/Registrations/RegistrationBase.cs +++ b/LightweightIocContainer/Registrations/RegistrationBase.cs @@ -5,41 +5,41 @@ using System; using System.Linq; using LightweightIocContainer.Exceptions; +using LightweightIocContainer.Factories; using LightweightIocContainer.Interfaces; +using LightweightIocContainer.Interfaces.Factories; using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations { /// - /// The that is used to register an Interface + /// The that is used to register an Interface /// - /// The registered Interface - public abstract class RegistrationBase : IRegistrationBase + public abstract class RegistrationBase : IRegistrationBase { + private readonly IocContainer _container; + /// - /// The that is used to register an Interface + /// The that is used to register an Interface /// /// The of the Interface /// The of the registration - protected RegistrationBase(Type interfaceType, Lifestyle lifestyle) + /// The current instance of the + protected RegistrationBase(Type interfaceType, Lifestyle lifestyle, IocContainer container) { InterfaceType = interfaceType; Lifestyle = lifestyle; + _container = container; } /// - /// The name of the - /// - public string Name { get; protected set; } - - /// - /// The of the Interface that is registered with this + /// The of the Interface that is registered with this /// public Type InterfaceType { get; } /// - /// The of Instances that are created with this + /// The of Instances that are created with this /// public Lifestyle Lifestyle { get; } @@ -48,15 +48,17 @@ namespace LightweightIocContainer.Registrations /// Can be set in the by calling /// public object[] Parameters { get; private set; } + + public ITypedFactory Factory { get; private set; } /// - /// Pass parameters that will be used to an instance of this + /// Pass parameters that will be used to an instance of this /// Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving /// /// The parameters - /// The current instance of this + /// The current instance of this /// are already set or no parameters given - public virtual IRegistrationBase WithParameters(params object[] parameters) + public virtual IRegistrationBase WithParameters(params object[] parameters) { if (Parameters != null) throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType})."); @@ -73,9 +75,9 @@ namespace LightweightIocContainer.Registrations /// Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving /// /// The parameters with their position - /// The current instance of this + /// The current instance of this /// are already set or no parameters given - public virtual IRegistrationBase WithParameters(params (int index, object parameter)[] parameters) + public virtual IRegistrationBase WithParameters(params (int index, object parameter)[] parameters) { if (Parameters != null) throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType})."); @@ -83,7 +85,7 @@ namespace LightweightIocContainer.Registrations if (parameters == null || !parameters.Any()) throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType})."); - var lastIndex = parameters.Max(p => p.index); + int lastIndex = parameters.Max(p => p.index); Parameters = new object[lastIndex + 1]; for (int i = 0; i < Parameters.Length; i++) @@ -96,5 +98,23 @@ namespace LightweightIocContainer.Registrations return this; } + + public IRegistrationBase WithFactory() + { + TypedFactory factory = new(_container); + + Factory = factory; + _container.RegisterFactory(factory); + + return this; + } + + public IRegistrationBase WithFactory() where TFactoryImplementation : TFactoryInterface + { + Factory = new CustomTypedFactory(); + _container.Register(); + + return this; + } } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/RegistrationFactory.cs b/LightweightIocContainer/Registrations/RegistrationFactory.cs index 663abfa..c6d67c9 100644 --- a/LightweightIocContainer/Registrations/RegistrationFactory.cs +++ b/LightweightIocContainer/Registrations/RegistrationFactory.cs @@ -3,7 +3,7 @@ // Copyright(c) 2019 SimonG. All Rights Reserved. using System; -using LightweightIocContainer.Interfaces; +using LightweightIocContainer.Interfaces.Factories; using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Registrations; @@ -14,9 +14,9 @@ namespace LightweightIocContainer.Registrations /// internal class RegistrationFactory { - private readonly IIocContainer _iocContainer; + private readonly IocContainer _iocContainer; - internal RegistrationFactory(IIocContainer container) => _iocContainer = container; + internal RegistrationFactory(IocContainer container) => _iocContainer = container; /// /// Register an Interface with a Type that implements it and create a @@ -25,8 +25,8 @@ namespace LightweightIocContainer.Registrations /// The Type that implements the interface /// The for this /// A new created with the given parameters - public IDefaultRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface => - new DefaultRegistration(typeof(TInterface), typeof(TImplementation), lifestyle); + public ITypedRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface => + new TypedRegistration(typeof(TInterface), typeof(TImplementation), lifestyle, _iocContainer); /// /// Register an open generic Interface with an open generic Type that implements it and create a @@ -35,7 +35,8 @@ namespace LightweightIocContainer.Registrations /// The open generic Type that implements the interface /// The for this /// The created - public IOpenGenericRegistration Register(Type tInterface, Type tImplementation, Lifestyle lifestyle) => new OpenGenericRegistration(tInterface, tImplementation, lifestyle); + public IOpenGenericRegistration Register(Type tInterface, Type tImplementation, Lifestyle lifestyle) => + new OpenGenericRegistration(tInterface, tImplementation, lifestyle, _iocContainer); /// /// Register multiple interfaces for a that implements them and create a @@ -46,7 +47,7 @@ namespace LightweightIocContainer.Registrations /// The for this /// The created public IMultipleRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2 => - new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), lifestyle); + new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), lifestyle, _iocContainer); /// /// Register multiple interfaces for a that implements them and create a @@ -58,7 +59,7 @@ namespace LightweightIocContainer.Registrations /// The for this /// The created public IMultipleRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3 => - new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TImplementation), lifestyle); + new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TImplementation), lifestyle, _iocContainer); /// /// Register multiple interfaces for a that implements them and create a @@ -71,7 +72,7 @@ namespace LightweightIocContainer.Registrations /// The for this /// The created public IMultipleRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4 => - new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TImplementation), lifestyle); + new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TImplementation), lifestyle, _iocContainer); /// /// Register multiple interfaces for a that implements them and create a @@ -85,7 +86,7 @@ namespace LightweightIocContainer.Registrations /// The for this /// The created public IMultipleRegistration Register(Lifestyle lifestyle) where TImplementation : TInterface1, TInterface2, TInterface3, TInterface4, TInterface5 => - new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TInterface5), typeof(TImplementation), lifestyle); + new MultipleRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TInterface3), typeof(TInterface4), typeof(TInterface5), typeof(TImplementation), lifestyle, _iocContainer); /// /// Register a without an interface and create a @@ -93,7 +94,7 @@ namespace LightweightIocContainer.Registrations /// The to register /// The for this /// A new created with the given parameters - public ISingleTypeRegistration Register(Lifestyle lifestyle) => new SingleTypeRegistration(typeof(T), lifestyle); + public ISingleTypeRegistration Register(Lifestyle lifestyle) => new SingleTypeRegistration(typeof(T), lifestyle, _iocContainer); /// /// Register an Interface with a Type that implements it as a multiton and create a @@ -103,7 +104,7 @@ namespace LightweightIocContainer.Registrations /// The Type of the multiton scope /// A new created with the given parameters public IMultitonRegistration RegisterMultiton() where TImplementation : TInterface => - new MultitonRegistration(typeof(TInterface), typeof(TImplementation), typeof(TScope)); + new MultitonRegistration(typeof(TInterface), typeof(TImplementation), typeof(TScope), _iocContainer); /// /// Register multiple interfaces for a that implements them as a multiton @@ -114,13 +115,13 @@ namespace LightweightIocContainer.Registrations /// The Type of the multiton scope /// A new created with the given parameters public IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2 => - new MultipleMultitonRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope)); + new MultipleMultitonRegistration(typeof(TInterface1), typeof(TInterface2), typeof(TImplementation), typeof(TScope), _iocContainer); /// /// Register an Interface as an abstract typed factory and create a /// /// The abstract typed factory to register /// A new created with the given parameters - public ITypedFactoryRegistration RegisterFactory() => new TypedFactoryRegistration(typeof(TFactory), _iocContainer); + public ITypedFactoryRegistration RegisterFactory(ITypedFactory factory) => new TypedFactoryRegistration(factory); } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs index ee7da72..a01e785 100644 --- a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs +++ b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs @@ -9,19 +9,22 @@ using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Registrations { /// - /// The to register either only an interface or only a + /// The to register either only an interface or only a /// - /// The of the - public class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration + /// The of the + public class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration { /// - /// The to register either only an interface or only a + /// The to register either only an interface or only a /// /// The of the interface or - /// The of the - public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle) - : base(interfaceType, lifestyle) => - Name = $"{InterfaceType.Name}, Lifestyle: {Lifestyle.ToString()}"; + /// The of the + /// The current instance of the + public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType, lifestyle, container) + { + + } /// /// that is invoked instead of creating an instance of this the default way @@ -32,7 +35,7 @@ namespace LightweightIocContainer.Registrations /// Pass a that will be invoked instead of creating an instance of this the default way /// /// The - /// The current instance of this + /// The current instance of this public ISingleTypeRegistration WithFactoryMethod(Func factoryMethod) { FactoryMethod = factoryMethod; diff --git a/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs b/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs index c84192b..984feac 100644 --- a/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs +++ b/LightweightIocContainer/Registrations/TypedFactoryRegistration.cs @@ -3,13 +3,6 @@ // Copyright(c) 2019 SimonG. All Rights Reserved. using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using LightweightIocContainer.Exceptions; -using LightweightIocContainer.Factories; -using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Factories; using LightweightIocContainer.Interfaces.Registrations; @@ -21,150 +14,20 @@ namespace LightweightIocContainer.Registrations /// The of the abstract typed factory public class TypedFactoryRegistration : ITypedFactoryRegistration { - private const string CLEAR_MULTITON_INSTANCE_METHOD_NAME = "ClearMultitonInstance"; - /// /// The registration that is used to register an abstract typed factory /// - /// The of the abstract typed factory - /// The current instance of the - public TypedFactoryRegistration(Type factoryType, IIocContainer container) - { - InterfaceType = factoryType; - Name = $"{InterfaceType.Name}"; - - CreateFactory(container); - } + /// The for this + public TypedFactoryRegistration(ITypedFactory factory) => Factory = factory; /// - /// The name of the + /// The of the factory that is registered with this /// - public string Name { get; } - - /// - /// The of the abstract typed factory that is registered with this - /// - public Type InterfaceType { get; } - + public Type InterfaceType => typeof(TFactory); + /// /// The class that contains the implemented abstract factory of this /// - public ITypedFactory Factory { get; private set; } - - - /// - /// Creates the factory from the given abstract factory type - /// - /// Factory registration is invalid - /// Creation of abstract methods are illegal in their current state - private void CreateFactory(IIocContainer container) - { - List createMethods = InterfaceType.GetMethods().Where(m => m.ReturnType != typeof(void)).ToList(); - if (!createMethods.Any()) - throw new InvalidFactoryRegistrationException($"Factory {Name} has no create methods."); - - Type type = typeof(TypedFactory<>); - Type factory = type.MakeGenericType(InterfaceType); - - Factory = (ITypedFactory) Activator.CreateInstance(factory); - - AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Factory"), AssemblyBuilderAccess.Run); - ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("Factory"); - TypeBuilder typeBuilder = moduleBuilder.DefineType($"TypedFactory.{InterfaceType.Name}"); - - typeBuilder.AddInterfaceImplementation(InterfaceType); - - //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(IIocContainer)}); - ILGenerator constructorGenerator = constructorBuilder.GetILGenerator(); - constructorGenerator.Emit(OpCodes.Ldarg_0); - constructorGenerator.Emit(OpCodes.Ldarg_1); - constructorGenerator.Emit(OpCodes.Stfld, containerFieldBuilder); //set `_container` field - constructorGenerator.Emit(OpCodes.Ret); - - foreach (MethodInfo createMethod in createMethods) - { - //create a method that looks like this - //public `createMethod.ReturnType` Create(`createMethod.GetParameters()`) - //{ - // return IIocContainer.Resolve(`createMethod.ReturnType`, params); - //} - - ParameterInfo[] args = createMethod.GetParameters(); - - MethodBuilder methodBuilder = typeBuilder.DefineMethod(createMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, - createMethod.ReturnType, (from arg in args select arg.ParameterType).ToArray()); - typeBuilder.DefineMethodOverride(methodBuilder, createMethod); - - ILGenerator generator = methodBuilder.GetILGenerator(); - - generator.Emit(OpCodes.Ldarg_0); - generator.Emit(OpCodes.Ldfld, containerFieldBuilder); - - if (args.Any()) - { - generator.Emit(OpCodes.Ldc_I4_S, args.Length); - generator.Emit(OpCodes.Newarr, typeof(object)); - - for (int i = 0; i < args.Length; i++) - { - generator.Emit(OpCodes.Dup); - generator.Emit(OpCodes.Ldc_I4_S, i); - generator.Emit(OpCodes.Ldarg_S, i + 1); - generator.Emit(OpCodes.Box, args[i].ParameterType); //Boxing is only needed for simple datatypes, but for now it is not a problem to box everything - generator.Emit(OpCodes.Stelem_Ref); - } - } - else - { - MethodInfo emptyArray = typeof(Array).GetMethod(nameof(Array.Empty))?.MakeGenericMethod(typeof(object)); - generator.EmitCall(OpCodes.Call, emptyArray, null); - } - - generator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.Resolve), new[] { typeof(object[]) })?.MakeGenericMethod(createMethod.ReturnType), null); - generator.Emit(OpCodes.Castclass, createMethod.ReturnType); - generator.Emit(OpCodes.Ret); - } - - //if factory contains a method to clear multiton instances - MethodInfo multitonClearMethod = InterfaceType.GetMethods().FirstOrDefault(m => m.Name.Equals(CLEAR_MULTITON_INSTANCE_METHOD_NAME)); - if (multitonClearMethod != null) - { - //create a method that looks like this - //public void ClearMultitonInstance() - //{ - // IIocContainer.ClearMultitonInstances(); - //} - - if (multitonClearMethod.IsGenericMethod) - { - Type typeToClear = multitonClearMethod.GetGenericArguments().FirstOrDefault(); - if (typeToClear == null) - throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); - - MethodBuilder multitonClearMethodBuilder = typeBuilder.DefineMethod(multitonClearMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, - multitonClearMethod.ReturnType, null); - multitonClearMethodBuilder.DefineGenericParameters(typeToClear.Name); - - typeBuilder.DefineMethodOverride(multitonClearMethodBuilder, multitonClearMethod); - - ILGenerator multitonClearGenerator = multitonClearMethodBuilder.GetILGenerator(); - multitonClearGenerator.Emit(OpCodes.Ldarg_0); - multitonClearGenerator.Emit(OpCodes.Ldfld, containerFieldBuilder); - - multitonClearGenerator.EmitCall(OpCodes.Callvirt, typeof(IIocContainer).GetMethod(nameof(IIocContainer.ClearMultitonInstances))?.MakeGenericMethod(typeToClear), null); - multitonClearGenerator.Emit(OpCodes.Ret); - } - else - { - throw new IllegalAbstractMethodCreationException("No Type to clear specified.", multitonClearMethod); - } - } - - Factory.Factory = (TFactory) Activator.CreateInstance(typeBuilder.CreateTypeInfo().AsType(), container); - } + public ITypedFactory Factory { get; } } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/TypedRegistrationBase.cs b/LightweightIocContainer/Registrations/TypedRegistration.cs similarity index 72% rename from LightweightIocContainer/Registrations/TypedRegistrationBase.cs rename to LightweightIocContainer/Registrations/TypedRegistration.cs index 4bd1a9d..acbe422 100644 --- a/LightweightIocContainer/Registrations/TypedRegistrationBase.cs +++ b/LightweightIocContainer/Registrations/TypedRegistration.cs @@ -3,16 +3,17 @@ // Copyright(c) 2019 SimonG. All Rights Reserved. using System; +using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Installers; using LightweightIocContainer.Interfaces.Registrations; -using LightweightIocContainer.Interfaces.Registrations.FluentProviders; +using LightweightIocContainer.Interfaces.Registrations.Fluent; namespace LightweightIocContainer.Registrations { /// /// A that implements a /// - public abstract class TypedRegistrationBase : RegistrationBase, ITypedRegistrationBase where TImplementation : TInterface + public class TypedRegistration : RegistrationBase, ITypedRegistration where TImplementation : TInterface { /// /// A that implements a @@ -20,8 +21,9 @@ namespace LightweightIocContainer.Registrations /// The of the interface /// The of the implementation type /// The of this - protected TypedRegistrationBase(Type interfaceType, Type implementationType, Lifestyle lifestyle) - : base(interfaceType, lifestyle) => + /// The current instance of the + public TypedRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle, IocContainer container) + : base(interfaceType, lifestyle, container) => ImplementationType = implementationType; /// @@ -39,8 +41,8 @@ namespace LightweightIocContainer.Registrations /// Pass an that will be invoked when an instance of this type is created /// /// The - /// The current instance of this - public virtual ITypedRegistrationBase OnCreate(Action action) + /// The current instance of this + public virtual ITypedRegistration OnCreate(Action action) { OnCreateAction = a => action((TImplementation) a); return this; diff --git a/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs new file mode 100644 index 0000000..8470dd6 --- /dev/null +++ b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs @@ -0,0 +1,230 @@ +// Author: Gockner, Simon +// Created: 2021-11-29 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using JetBrains.Annotations; +using LightweightIocContainer; +using LightweightIocContainer.Exceptions; +using LightweightIocContainer.Interfaces; +using NUnit.Framework; + +namespace Test.LightweightIocContainer +{ + [TestFixture] + public class FluentFactoryRegistrationTest + { + public interface ITest + { + + } + + private class Test : ITest + { + + } + + private class TestByte : ITest + { + [UsedImplicitly] + private readonly byte _id; + + public TestByte(byte id) => _id = id; + } + + [UsedImplicitly] + private class TestConstructor : ITest + { + public TestConstructor(string name, Test test) + { + + } + + public TestConstructor(Test test, string name = null) + { + + } + } + + private interface ITestFactoryNoCreate + { + + } + + private interface ITestFactoryNonGenericClear + { + ITest Create(); + + void ClearMultitonInstance(); + } + + [UsedImplicitly] + public interface ITestFactory + { + ITest Create(); + ITest Create(string name); + ITest Create(MultitonScope scope); + ITest CreateTest(string name = null); + ITest Create(byte id); + + void ClearMultitonInstance(); + } + + private class TestFactory : ITestFactory + { + public ITest Create() => new Test(); + public ITest Create(string name) => throw new System.NotImplementedException(); + public ITest Create(MultitonScope scope) => throw new System.NotImplementedException(); + public ITest CreateTest(string name = null) => throw new System.NotImplementedException(); + public ITest Create(byte id) => throw new System.NotImplementedException(); + public void ClearMultitonInstance() => throw new System.NotImplementedException(); + } + + public class MultitonScope + { + + } + + private IIocContainer _iocContainer; + + [SetUp] + public void SetUp() => _iocContainer = new IocContainer(); + + [TearDown] + public void TearDown() => _iocContainer.Dispose(); + + [Test] + public void TestFluentFactoryRegistration() + { + _iocContainer.Register().WithFactory(); + + ITestFactory factory = _iocContainer.Resolve(); + ITest test = _iocContainer.Resolve(); + + Assert.IsInstanceOf(factory); + Assert.IsInstanceOf(test); + } + + [Test] + public void TestFluentFactoryRegistration_CustomFactory() + { + _iocContainer.Register().WithFactory(); + + ITestFactory factory = _iocContainer.Resolve(); + ITest test = _iocContainer.Resolve(); + + Assert.IsInstanceOf(factory); + Assert.IsInstanceOf(test); + } + + [Test] + public void TestRegisterFactoryWithoutCreate() => Assert.Throws(() => _iocContainer.Register().WithFactory()); + + [Test] + public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws(() => _iocContainer.Register().WithFactory()); + + [Test] + public void TestResolveFromFactory() + { + _iocContainer.Register().WithFactory(); + + ITestFactory testFactory = _iocContainer.Resolve(); + ITest createdTest = testFactory.Create(); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveFromFactoryWithParams() + { + _iocContainer.Register().WithFactory(); + _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + + ITestFactory testFactory = _iocContainer.Resolve(); + ITest createdTest = testFactory.Create("Test"); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveFromFactoryWithDefaultParamCreate() + { + _iocContainer.Register().WithFactory(); + _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + + ITestFactory testFactory = _iocContainer.Resolve(); + ITest createdTest = testFactory.CreateTest(); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveFromFactoryWithDefaultParamCtor() + { + _iocContainer.Register().WithFactory(); + _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + + ITestFactory testFactory = _iocContainer.Resolve(); + ITest createdTest = testFactory.Create(); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveFromFactoryWithByte() + { + _iocContainer.Register().WithFactory(); + + ITestFactory testFactory = _iocContainer.Resolve(); + ITest createdTest = testFactory.Create(1); + + Assert.IsInstanceOf(createdTest); + } + + [Test] + public void TestResolveMultitonFromFactory() + { + _iocContainer.RegisterMultiton().WithFactory(); + + MultitonScope scope1 = new MultitonScope(); + MultitonScope scope2 = new MultitonScope(); + + ITestFactory testFactory = _iocContainer.Resolve(); + + ITest resolvedTest1 = testFactory.Create(scope1); + ITest resolvedTest2 = testFactory.Create(scope1); + ITest resolvedTest3 = testFactory.Create(scope2); + + Assert.AreSame(resolvedTest1, resolvedTest2); + Assert.AreNotSame(resolvedTest1, resolvedTest3); + Assert.AreNotSame(resolvedTest2, resolvedTest3); + } + + [Test] + public void TestResolveMultitonFromFactoryClearInstances() + { + _iocContainer.RegisterMultiton().WithFactory(); + + MultitonScope scope1 = new MultitonScope(); + MultitonScope scope2 = new MultitonScope(); + + ITestFactory testFactory = _iocContainer.Resolve(); + + ITest resolvedTest1 = testFactory.Create(scope1); + ITest resolvedTest2 = testFactory.Create(scope1); + ITest resolvedTest3 = testFactory.Create(scope2); + + Assert.AreSame(resolvedTest1, resolvedTest2); + Assert.AreNotSame(resolvedTest1, resolvedTest3); + Assert.AreNotSame(resolvedTest2, resolvedTest3); + + testFactory.ClearMultitonInstance(); + + ITest resolvedTest4 = testFactory.Create(scope1); + ITest resolvedTest5 = testFactory.Create(scope2); + + Assert.AreNotSame(resolvedTest1, resolvedTest4); + Assert.AreNotSame(resolvedTest2, resolvedTest4); + Assert.AreNotSame(resolvedTest3, resolvedTest5); + } + } +} \ No newline at end of file diff --git a/Test.LightweightIocContainer/IocContainerTest.cs b/Test.LightweightIocContainer/IocContainerTest.cs index f8efff4..dfcbedd 100644 --- a/Test.LightweightIocContainer/IocContainerTest.cs +++ b/Test.LightweightIocContainer/IocContainerTest.cs @@ -11,35 +11,11 @@ namespace Test.LightweightIocContainer [TestFixture] public class IocContainerTest { - public interface ITest + private interface ITest { } - [UsedImplicitly] - public interface ITestFactory - { - ITest Create(); - ITest Create(string name); - ITest Create(MultitonScope scope); - ITest CreateTest(string name = null); - ITest Create(byte id); - - void ClearMultitonInstance(); - } - - private interface ITestFactoryNoCreate - { - - } - - private interface ITestFactoryNonGenericClear - { - ITest Create(); - - void ClearMultitonInstance(); - } - private interface IFoo { @@ -92,22 +68,13 @@ namespace Test.LightweightIocContainer } } - [UsedImplicitly] - private class TestByte : ITest - { - [UsedImplicitly] - private readonly byte _id; - - public TestByte(byte id) => _id = id; - } - [UsedImplicitly] private class Foo : IFoo { } - public class MultitonScope + private class MultitonScope { } @@ -161,9 +128,6 @@ namespace Test.LightweightIocContainer [Test] public void TestInvalidMultitonRegistration() => Assert.Throws(() => _iocContainer.Register(Lifestyle.Multiton)); - [Test] - public void TestRegisterFactory() => Assert.DoesNotThrow(() => _iocContainer.RegisterFactory()); - [Test] public void TestRegisterMultiple() { @@ -172,12 +136,6 @@ namespace Test.LightweightIocContainer Assert.AreEqual(typeof(ITest), exception.Type); } - [Test] - public void TestRegisterFactoryWithoutCreate() => Assert.Throws(() => _iocContainer.RegisterFactory()); - - [Test] - public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws(() => _iocContainer.RegisterFactory()); - [Test] public void TestResolveNotRegistered() { @@ -323,129 +281,6 @@ namespace Test.LightweightIocContainer Assert.AreEqual(typeof(TestPrivateConstructor), exception.Type); } - [Test] - public void TestResolveFactory() - { - _iocContainer.Register(); - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - - Assert.IsInstanceOf(testFactory); - } - - [Test] - public void TestResolveFromFactory() - { - _iocContainer.Register(); - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - ITest createdTest = testFactory.Create(); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveFromFactoryWithParams() - { - _iocContainer.Register(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - ITest createdTest = testFactory.Create("Test"); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveFromFactoryWithDefaultParamCreate() - { - _iocContainer.Register(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - ITest createdTest = testFactory.CreateTest(); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveFromFactoryWithDefaultParamCtor() - { - _iocContainer.Register(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - ITest createdTest = testFactory.Create(); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveFromFactoryWithByte() - { - _iocContainer.Register(); - _iocContainer.RegisterFactory(); - - ITestFactory testFactory = _iocContainer.Resolve(); - ITest createdTest = testFactory.Create(1); - - Assert.IsInstanceOf(createdTest); - } - - [Test] - public void TestResolveMultitonFromFactory() - { - _iocContainer.RegisterMultiton(); - _iocContainer.RegisterFactory(); - - MultitonScope scope1 = new MultitonScope(); - MultitonScope scope2 = new MultitonScope(); - - ITestFactory testFactory = _iocContainer.Resolve(); - - ITest resolvedTest1 = testFactory.Create(scope1); - ITest resolvedTest2 = testFactory.Create(scope1); - ITest resolvedTest3 = testFactory.Create(scope2); - - Assert.AreSame(resolvedTest1, resolvedTest2); - Assert.AreNotSame(resolvedTest1, resolvedTest3); - Assert.AreNotSame(resolvedTest2, resolvedTest3); - } - - [Test] - public void TestResolveMultitonFromFactoryClearInstances() - { - _iocContainer.RegisterMultiton(); - _iocContainer.RegisterFactory(); - - MultitonScope scope1 = new MultitonScope(); - MultitonScope scope2 = new MultitonScope(); - - ITestFactory testFactory = _iocContainer.Resolve(); - - ITest resolvedTest1 = testFactory.Create(scope1); - ITest resolvedTest2 = testFactory.Create(scope1); - ITest resolvedTest3 = testFactory.Create(scope2); - - Assert.AreSame(resolvedTest1, resolvedTest2); - Assert.AreNotSame(resolvedTest1, resolvedTest3); - Assert.AreNotSame(resolvedTest2, resolvedTest3); - - testFactory.ClearMultitonInstance(); - - ITest resolvedTest4 = testFactory.Create(scope1); - ITest resolvedTest5 = testFactory.Create(scope2); - - Assert.AreNotSame(resolvedTest1, resolvedTest4); - Assert.AreNotSame(resolvedTest2, resolvedTest4); - Assert.AreNotSame(resolvedTest3, resolvedTest5); - } - [Test] public void TestResolveSingleTypeRegistrationWithFactoryMethod() { diff --git a/Test.LightweightIocContainer/OnCreateTest.cs b/Test.LightweightIocContainer/OnCreateTest.cs index 12c197b..bc42d49 100644 --- a/Test.LightweightIocContainer/OnCreateTest.cs +++ b/Test.LightweightIocContainer/OnCreateTest.cs @@ -29,8 +29,8 @@ namespace Test.LightweightIocContainer [Test] public void TestOnCreate() { - RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); - ITypedRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).OnCreate(t => t.DoSomething()); + RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); + ITypedRegistration testRegistration = registrationFactory.Register(Lifestyle.Transient).OnCreate(t => t.DoSomething()); Test test = new Test(); diff --git a/Test.LightweightIocContainer/RegistrationBaseTest.cs b/Test.LightweightIocContainer/RegistrationBaseTest.cs index 2169223..ac2f4cd 100644 --- a/Test.LightweightIocContainer/RegistrationBaseTest.cs +++ b/Test.LightweightIocContainer/RegistrationBaseTest.cs @@ -5,7 +5,6 @@ using JetBrains.Annotations; using LightweightIocContainer; using LightweightIocContainer.Exceptions; -using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; using LightweightIocContainer.Registrations; using Moq; @@ -54,12 +53,12 @@ namespace Test.LightweightIocContainer [Test] public void TestWithParameters() { - RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); + RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); IBar bar = new Bar(); ITest test = new Test(); - IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters(bar, test); + IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters(bar, test); Assert.AreEqual(bar, testRegistration.Parameters[0]); Assert.AreEqual(test, testRegistration.Parameters[1]); @@ -68,12 +67,12 @@ namespace Test.LightweightIocContainer [Test] public void TestWithParametersDifferentOrder() { - RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); + RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); IBar bar = new Bar(); ITest test = new Test(); - IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString")); + IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString")); Assert.AreEqual(bar, testRegistration.Parameters[0]); Assert.IsInstanceOf(testRegistration.Parameters[1]); @@ -84,7 +83,7 @@ namespace Test.LightweightIocContainer [Test] public void TestWithParametersCalledTwice() { - RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); + RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters(new Bar()).WithParameters(new Test())); Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters((0, new Bar())).WithParameters((1, new Test()))); } @@ -92,7 +91,7 @@ namespace Test.LightweightIocContainer [Test] public void TestWithParametersNoParametersGiven() { - RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); + RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object); Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters((object[])null)); Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters(((int index, object parameter)[])null)); } diff --git a/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs index 1b02035..da8e87e 100644 --- a/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs +++ b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs @@ -45,7 +45,7 @@ namespace Test.LightweightIocContainer { IBar bar = new Bar(); - Mock iocContainerMock = new Mock(); + Mock iocContainerMock = new(); iocContainerMock.Setup(c => c.Resolve()).Returns(bar); RegistrationFactory registrationFactory = new RegistrationFactory(iocContainerMock.Object);