From 3acd6adfea8a1eb7f0b3232ad27fa48088759e64 Mon Sep 17 00:00:00 2001 From: Simon G Date: Thu, 16 Dec 2021 10:41:34 +0100 Subject: [PATCH] - completely rework registration: - creation of registrations is done in registrationCollector now - installers don't get container anymore, get registrationCollector - allow validation - introduce dispose strategies (#55) --- LightweightIocContainer/DisposeStrategy.cs | 29 + .../EnumerableExtension.cs | 12 + .../InvalidDisposeStrategyException.cs | 25 + .../Installers/AssemblyInstaller.cs | 7 +- .../Interfaces/IIocContainer.cs | 91 --- .../Interfaces/Installers/IIocInstaller.cs | 4 +- .../Fluent/IWithDisposeStrategy.cs | 28 + .../IInternalValidationProvider.cs | 16 + .../Registrations/IRegistrationBase.cs | 2 +- .../Registrations/IRegistrationCollector.cs | 104 ++++ LightweightIocContainer/IocContainer.cs | 215 ++----- .../LightweightIocContainer.csproj | 4 +- .../LightweightIocContainer.xml | 534 +++++++++++------- .../MultipleMultitonRegistration.cs | 2 +- .../Registrations/MultipleRegistration.cs | 10 +- .../Registrations/MultitonRegistration.cs | 2 +- .../Registrations/OpenGenericRegistration.cs | 17 +- .../Registrations/RegistrationBase.cs | 80 ++- .../Registrations/RegistrationCollector.cs | 188 ++++++ .../Registrations/SingleTypeRegistration.cs | 2 +- .../Registrations/TypedRegistration.cs | 7 +- .../AssemblyInstallerTest.cs | 8 +- .../DisposeStrategyTest.cs | 91 +++ .../EnumerableExtensionTest.cs | 26 + .../FluentFactoryRegistrationTest.cs | 30 +- .../IocContainerInterfaceSegregationTest.cs | 12 +- .../IocContainerParameterRegistrationTest.cs | 12 +- .../IocContainerRecursionTest.cs | 18 +- .../IocContainerTest.cs | 67 +-- .../IocValidatorTest.cs | 6 +- .../MultiLayerResolveTest.cs | 10 +- .../MultipleMultitonRegistrationTest.cs | 6 +- Test.LightweightIocContainer/OnCreateTest.cs | 4 +- .../OpenGenericRegistrationTest.cs | 8 +- .../RegistrationBaseTest.cs | 4 +- .../SingleTypeRegistrationTest.cs | 6 +- 36 files changed, 1104 insertions(+), 583 deletions(-) create mode 100644 LightweightIocContainer/DisposeStrategy.cs create mode 100644 LightweightIocContainer/Exceptions/InvalidDisposeStrategyException.cs create mode 100644 LightweightIocContainer/Interfaces/Registrations/Fluent/IWithDisposeStrategy.cs create mode 100644 LightweightIocContainer/Interfaces/Registrations/IInternalValidationProvider.cs create mode 100644 LightweightIocContainer/Interfaces/Registrations/IRegistrationCollector.cs create mode 100644 LightweightIocContainer/Registrations/RegistrationCollector.cs create mode 100644 Test.LightweightIocContainer/DisposeStrategyTest.cs diff --git a/LightweightIocContainer/DisposeStrategy.cs b/LightweightIocContainer/DisposeStrategy.cs new file mode 100644 index 0000000..91b365d --- /dev/null +++ b/LightweightIocContainer/DisposeStrategy.cs @@ -0,0 +1,29 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; + +namespace LightweightIocContainer; + +/// +/// The dispose strategy that is used for a singleton or multiton that implements and is created by the +/// +public enum DisposeStrategy +{ + /// + /// No dispose strategy + /// Invalid for singletons or multitons that implement + /// + None, + + /// + /// The application is responsible for correctly disposing the instance. Nothing is done by the + /// + Application, + + /// + /// The is responsible for disposing the instance when itself is disposed + /// + Container +} \ No newline at end of file diff --git a/LightweightIocContainer/EnumerableExtension.cs b/LightweightIocContainer/EnumerableExtension.cs index e7b5204..16ec33e 100644 --- a/LightweightIocContainer/EnumerableExtension.cs +++ b/LightweightIocContainer/EnumerableExtension.cs @@ -50,5 +50,17 @@ namespace LightweightIocContainer return new TGiven(); } } + + /// + /// Executes an for each item in an + /// + /// The + /// The + /// The of the items in the + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (T item in enumerable) + action(item); + } } } \ No newline at end of file diff --git a/LightweightIocContainer/Exceptions/InvalidDisposeStrategyException.cs b/LightweightIocContainer/Exceptions/InvalidDisposeStrategyException.cs new file mode 100644 index 0000000..9e4e6db --- /dev/null +++ b/LightweightIocContainer/Exceptions/InvalidDisposeStrategyException.cs @@ -0,0 +1,25 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; + +namespace LightweightIocContainer.Exceptions; + +/// +/// Invalid is used +/// +public class InvalidDisposeStrategyException : IocContainerException +{ + /// + /// Invalid is used + /// + /// The + /// The + /// The + public InvalidDisposeStrategyException(DisposeStrategy disposeStrategy, Type type, Lifestyle lifestyle) + : base($"Dispose strategy {disposeStrategy} is invalid for the type {type} and lifestyle {lifestyle}.") + { + + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Installers/AssemblyInstaller.cs b/LightweightIocContainer/Installers/AssemblyInstaller.cs index 9fc8c0d..414daac 100644 --- a/LightweightIocContainer/Installers/AssemblyInstaller.cs +++ b/LightweightIocContainer/Installers/AssemblyInstaller.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Reflection; using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Installers; +using LightweightIocContainer.Interfaces.Registrations; namespace LightweightIocContainer.Installers { @@ -41,11 +42,11 @@ namespace LightweightIocContainer.Installers /// /// Install the found s in the given /// - /// The current - public void Install(IIocContainer container) + /// The where s are added + public void Install(IRegistrationCollector registration) { foreach (IIocInstaller installer in Installers) - installer.Install(container); + installer.Install(registration); } } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/IIocContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs index e7fc31b..b86f5d0 100644 --- a/LightweightIocContainer/Interfaces/IIocContainer.cs +++ b/LightweightIocContainer/Interfaces/IIocContainer.cs @@ -20,97 +20,6 @@ namespace LightweightIocContainer.Interfaces /// An instance of the current IIocContainer Install(params IIocInstaller[] installers); - /// - /// Register an Interface with a Type that implements it - /// - /// The Interface to register - /// The Type that implements the interface - /// The for this - /// The created - 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 created - IOpenGenericRegistration RegisterOpenGenerics(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient); - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// The that implements both interfaces - /// The for this - /// The created - IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1; - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// The that implements both interfaces - /// The for this - /// The created - IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface3, TInterface2, TInterface1; - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// A fourth interface to register - /// The that implements both interfaces - /// The for this - /// The created - IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1; - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// A fourth interface to register - /// A fifth interface to register - /// The that implements both interfaces - /// The for this - /// The created - IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1; - - /// - /// Register a without an interface - /// - /// The to register - /// The for this - /// The created - ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient); - - /// - /// Register an Interface with a Type that implements it as a multiton - /// - /// The Interface to register - /// The Type that implements the interface - /// The Type of the multiton scope - /// The created - IMultitonRegistration RegisterMultiton() where TImplementation : TInterface; - - /// - /// Register multiple interfaces for a that implements them as a multiton - /// - /// The base interface to register - /// A second interface to register - /// The Type that implements the interface - /// The Type of the multiton scope - /// The created - IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2; - /// /// Clear the multiton instances of the given from the registered multitons list /// diff --git a/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs b/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs index d329bd4..ae4f44c 100644 --- a/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs +++ b/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs @@ -14,7 +14,7 @@ namespace LightweightIocContainer.Interfaces.Installers /// /// Install the needed s in the given /// - /// The current - void Install(IIocContainer container); + /// The where s are added + void Install(IRegistrationCollector registration); } } \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithDisposeStrategy.cs b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithDisposeStrategy.cs new file mode 100644 index 0000000..8f07ccd --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/Fluent/IWithDisposeStrategy.cs @@ -0,0 +1,28 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; + +namespace LightweightIocContainer.Interfaces.Registrations.Fluent; + +/// +/// Provides a to an +/// +public interface IWithDisposeStrategy +{ + /// + /// Add a for the + /// + /// The + /// The current instance of this + IRegistrationBase WithDisposeStrategy(DisposeStrategy disposeStrategy); +} + +internal interface IWithDisposeStrategyInternal : IWithDisposeStrategy +{ + /// + /// The of singletons/multitons that implement and are created with this + /// + DisposeStrategy DisposeStrategy { get; } +} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IInternalValidationProvider.cs b/LightweightIocContainer/Interfaces/Registrations/IInternalValidationProvider.cs new file mode 100644 index 0000000..ed9f879 --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/IInternalValidationProvider.cs @@ -0,0 +1,16 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +namespace LightweightIocContainer.Interfaces.Registrations; + +/// +/// Provides an internal method to an +/// +internal interface IInternalValidationProvider +{ + /// + /// Validate this + /// + void Validate(); +} \ No newline at end of file diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs index d729663..f5ca85b 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs @@ -9,7 +9,7 @@ namespace LightweightIocContainer.Interfaces.Registrations /// /// The that is used to register an Interface and extends the with fluent options /// - public interface IRegistrationBase : IRegistration, IWithFactory, IWithParameters + public interface IRegistrationBase : IRegistration, IWithFactory, IWithParameters, IWithDisposeStrategy { } diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistrationCollector.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistrationCollector.cs new file mode 100644 index 0000000..f4c32d8 --- /dev/null +++ b/LightweightIocContainer/Interfaces/Registrations/IRegistrationCollector.cs @@ -0,0 +1,104 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; + +namespace LightweightIocContainer.Interfaces.Registrations; + +/// +/// Creates and collects the s +/// +public interface IRegistrationCollector +{ + /// + /// Add an Interface with a Type that implements it + /// + /// The Interface to add + /// The Type that implements the interface + /// The for this + /// The created + ITypedRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface; + + /// + /// Add an open generic Interface with an open generic Type that implements it + /// + /// The open generic Interface to add + /// The open generic Type that implements the interface + /// The for this + /// The created + IOpenGenericRegistration AddOpenGenerics(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient); + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// The that implements both interfaces + /// The for this + /// The created + IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1; + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// The that implements both interfaces + /// The for this + /// The created + IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface3, TInterface2, TInterface1; + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// A fourth interface to add + /// The that implements both interfaces + /// The for this + /// The created + IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1; + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// A fourth interface to add + /// A fifth interface to add + /// The that implements both interfaces + /// The for this + /// The created + IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1; + + /// + /// Add a without an interface + /// + /// The to add + /// The for this + /// The created + ISingleTypeRegistration Add(Lifestyle lifestyle = Lifestyle.Transient); + + /// + /// Add an Interface with a Type that implements it as a multiton + /// + /// The Interface to add + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + IMultitonRegistration AddMultiton() where TImplementation : TInterface; + + /// + /// Add multiple interfaces for a that implements them as a multiton + /// + /// The base interface to add + /// A second interface to add + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + IMultipleMultitonRegistration AddMultiton() where TImplementation : TInterface1, TInterface2; +} \ No newline at end of file diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs index edc5f9c..2c7e393 100644 --- a/LightweightIocContainer/IocContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -47,162 +47,26 @@ namespace LightweightIocContainer public IIocContainer Install(params IIocInstaller[] installers) { foreach (IIocInstaller installer in installers) - installer.Install(this); + { + RegistrationCollector registrationCollector = new(_registrationFactory); + installer.Install(registrationCollector); + + registrationCollector.Registrations.ForEach(Register); + } return this; } /// - /// Register an Interface with a Type that implements it - /// - /// The Interface to register - /// The Type that implements the interface - /// The for this - /// The created - public ITypedRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface - { - ITypedRegistration registration = _registrationFactory.Register(lifestyle); - Register(registration); - - return registration; - } - - /// - /// Register an open generic Interface with an open generic Type that implements it + /// Register an at this /// - /// The open generic Interface to register - /// The open generic Type that implements the interface - /// The for this - /// The created - /// Function can only be used to register open generic types - /// Can't register a multiton with open generic registration - public IOpenGenericRegistration RegisterOpenGenerics(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient) + /// The that creates an + public void Register(Func addRegistration) { - if (!tInterface.ContainsGenericParameters) - throw new InvalidRegistrationException("This function can only be used to register open generic types."); - - if (lifestyle == Lifestyle.Multiton) - throw new InvalidRegistrationException("Can't register a multiton with open generic registration."); //TODO: Is there any need for a possibility to register multitons with open generics? + RegistrationCollector registrationCollector = new(_registrationFactory); + addRegistration(registrationCollector); - IOpenGenericRegistration registration = _registrationFactory.Register(tInterface, tImplementation, lifestyle); - Register(registration); - - return registration; - } - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// The that implements both interfaces - /// The for this - /// The created - public IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1 - { - IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); - Register(multipleRegistration); - - return multipleRegistration; - } - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// The that implements both interfaces - /// The for this - /// The created - public IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface3, TInterface2, TInterface1 - { - IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); - Register(multipleRegistration); - - return multipleRegistration; - } - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// A fourth interface to register - /// The that implements both interfaces - /// The for this - /// The created - public IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1 - { - IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); - Register(multipleRegistration); - - return multipleRegistration; - } - - /// - /// Register multiple interfaces for a that implements them - /// - /// The base interface to register - /// A second interface to register - /// A third interface to register - /// A fourth interface to register - /// A fifth interface to register - /// The that implements both interfaces - /// The for this - /// The created - public IMultipleRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1 - { - IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); - Register(multipleRegistration); - - return multipleRegistration; - } - - /// - /// Register a without an interface - /// - /// The to register - /// The for this - /// The created - public ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) - { - ISingleTypeRegistration registration = _registrationFactory.Register(lifestyle); - Register(registration); - - return registration; - } - - /// - /// Register an Interface with a Type that implements it as a multiton - /// - /// The Interface to register - /// The Type that implements the interface - /// The Type of the multiton scope - /// The created - public IMultitonRegistration RegisterMultiton() where TImplementation : TInterface - { - IMultitonRegistration registration = _registrationFactory.RegisterMultiton(); - Register(registration); - - return registration; - } - - /// - /// Register multiple interfaces for a that implements them as a multiton - /// - /// The base interface to register - /// A second interface to register - /// The Type that implements the interface - /// The Type of the multiton scope - /// The created - public IMultipleMultitonRegistration RegisterMultiton() where TImplementation : TInterface1, TInterface2 - { - IMultipleMultitonRegistration registration = _registrationFactory.RegisterMultiton(); - Register(registration); - - return registration; + registrationCollector.Registrations.ForEach(Register); } /// @@ -224,29 +88,16 @@ namespace LightweightIocContainer /// The is already registered in this private void Register(IRegistration registration) { - //if type is already registered + //if type is already registered //fixMe: Remove and check if already registered registration is the same if (Registrations.Any(r => r.InterfaceType == registration.InterfaceType)) throw new MultipleRegistrationException(registration.InterfaceType); - //don't allow lifestyle.multiton without iMultitonRegistration - if (registration is ILifestyleProvider { Lifestyle: Lifestyle.Multiton } and not IMultitonRegistration) - throw new InvalidRegistrationException("Can't register a type as Lifestyle.Multiton without a scope (Registration is not of type IMultitonRegistration)."); - + if (registration is IInternalValidationProvider validationProvider) + validationProvider.Validate(); + Registrations.Add(registration); } - /// - /// Register all from an - /// - /// The of the first registered interface - /// The of the registered implementation - /// The - private void Register(IMultipleRegistration multipleRegistration) where TImplementation : TInterface1 - { - foreach (IRegistration registration in multipleRegistration.Registrations) - Register(registration); - } - /// /// Gets an instance of the given /// @@ -685,9 +536,15 @@ namespace LightweightIocContainer /// /// The given /// The for the given - private IRegistration? FindRegistration() + private IRegistration? FindRegistration() => FindRegistration(typeof(T)); + + /// + /// Find the for the given + /// + /// The given + /// The for the given + private IRegistration? FindRegistration(Type type) { - Type type = typeof(T); IRegistration? registration = Registrations.FirstOrDefault(r => r.InterfaceType == type); if (registration != null) return registration; @@ -784,20 +641,18 @@ namespace LightweightIocContainer /// public void Dispose() { - Registrations.Clear(); - - foreach (var singleton in _singletons) - { - if (singleton.instance is IDisposable disposable) - disposable.Dispose(); - } - - foreach (var multitonInstance in _multitons.SelectMany(multiton => multiton.instances)) - { - if (multitonInstance.Value is IDisposable disposable) - disposable.Dispose(); - } + _singletons.Where(s => FindRegistration(s.type) is IWithDisposeStrategyInternal {DisposeStrategy: DisposeStrategy.Container}) + .Select(s => s.instance) + .OfType() + .ForEach(d => d.Dispose()); + + _multitons.Where(m => FindRegistration(m.type) is IWithDisposeStrategyInternal {DisposeStrategy: DisposeStrategy.Container}) + .SelectMany(m => m.instances) + .Select(i => i.Value) + .OfType() + .ForEach(d => d.Dispose()); + Registrations.Clear(); _singletons.Clear(); _multitons.Clear(); } diff --git a/LightweightIocContainer/LightweightIocContainer.csproj b/LightweightIocContainer/LightweightIocContainer.csproj index c851b70..beb4dbf 100644 --- a/LightweightIocContainer/LightweightIocContainer.csproj +++ b/LightweightIocContainer/LightweightIocContainer.csproj @@ -32,8 +32,8 @@ - - + + diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml index 01023d2..b0613d0 100644 --- a/LightweightIocContainer/LightweightIocContainer.xml +++ b/LightweightIocContainer/LightweightIocContainer.xml @@ -28,6 +28,27 @@ A new instance of the given The given type could not be created + + + The dispose strategy that is used for a singleton or multiton that implements and is created by the + + + + + No dispose strategy + Invalid for singletons or multitons that implement + + + + + The application is responsible for correctly disposing the instance. Nothing is done by the + + + + + The is responsible for disposing the instance when itself is disposed + + Returns the first element of a , or a new instance of a given if the contains no elements @@ -57,6 +78,14 @@ A function to test each element for a condition The first element of the or a new instance of the given when no element is found + + + Executes an for each item in an + + The + The + The of the items in the + A circular dependency was detected during @@ -140,6 +169,19 @@ The exception message + + + Invalid is used + + + + + Invalid is used + + The + The + The + The registration of a Factory is not valid @@ -373,11 +415,11 @@ The s of the Assembly that this is installing - + Install the found s in the given - The current + The where s are added @@ -430,97 +472,6 @@ The given s An instance of the current - - - Register an Interface with a Type that implements it - - The Interface to register - The Type that implements the interface - The for this - The created - - - - 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 created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - A fourth interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - A fourth interface to register - A fifth interface to register - The that implements both interfaces - The for this - The created - - - - Register a without an interface - - The to register - The for this - The created - - - - Register an Interface with a Type that implements it as a multiton - - The Interface to register - The Type that implements the interface - The Type of the multiton scope - The created - - - - Register multiple interfaces for a that implements them as a multiton - - The base interface to register - A second interface to register - The Type that implements the interface - The Type of the multiton scope - The created - Clear the multiton instances of the given from the registered multitons list @@ -549,11 +500,11 @@ The base class for installers - + Install the needed s in the given - The current + The where s are added @@ -600,6 +551,23 @@ The The current instance of this + + + Provides a to an + + + + + Add a for the + + The + The current instance of this + + + + The of singletons/multitons that implement and are created with this + + Provides a method to an @@ -654,6 +622,16 @@ Can be set in the by calling + + + Provides an internal method to an + + + + + Validate this + + Provides a to an @@ -759,6 +737,102 @@ The that is used to register an Interface and extends the with fluent options + + + Creates and collects the s + + + + + Add an Interface with a Type that implements it + + The Interface to add + The Type that implements the interface + The for this + The created + + + + Add an open generic Interface with an open generic Type that implements it + + The open generic Interface to add + The open generic Type that implements the interface + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + A fourth interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + A fourth interface to add + A fifth interface to add + The that implements both interfaces + The for this + The created + + + + Add a without an interface + + The to add + The for this + The created + + + + Add an Interface with a Type that implements it as a multiton + + The Interface to add + The Type that implements the interface + The Type of the multiton scope + The created + + + + Add multiple interfaces for a that implements them as a multiton + + The base interface to add + A second interface to add + The Type that implements the interface + The Type of the multiton scope + The created + The to register either only an interface or only a @@ -820,98 +894,11 @@ The given s An instance of the current - - - Register an Interface with a Type that implements it - - The Interface to register - The Type that implements the interface - The for this - The created - - + - Register an open generic Interface with an open generic Type that implements it + Register an at this - The open generic Interface to register - The open generic Type that implements the interface - The for this - The created - Function can only be used to register open generic types - Can't register a multiton with open generic registration - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - A fourth interface to register - The that implements both interfaces - The for this - The created - - - - Register multiple interfaces for a that implements them - - The base interface to register - A second interface to register - A third interface to register - A fourth interface to register - A fifth interface to register - The that implements both interfaces - The for this - The created - - - - Register a without an interface - - The to register - The for this - The created - - - - Register an Interface with a Type that implements it as a multiton - - The Interface to register - The Type that implements the interface - The Type of the multiton scope - The created - - - - Register multiple interfaces for a that implements them as a multiton - - The base interface to register - A second interface to register - The Type that implements the interface - The Type of the multiton scope - The created + The that creates an @@ -927,14 +914,6 @@ The given The is already registered in this - - - Register all from an - - The of the first registered interface - The of the registered implementation - The - Gets an instance of the given @@ -1117,6 +1096,13 @@ The given The for the given + + + Find the for the given + + The given + The for the given + Try to get the sorted constructors for the given @@ -1384,6 +1370,11 @@ The that implements the that is registered with this + + + Validate this + + The that is used to register an Interface @@ -1407,6 +1398,11 @@ The of Instances that are created with this + + + The of singletons/multitons that implement and are created with this + + An of parameters that are used to an instance of this @@ -1451,6 +1447,153 @@ The type of the implementation for the custom factory The current instance of this + + + Add a for the + + The + The current instance of this + + + + Validate this + + + + + Validate that no registration that isn't derived from has + + + + + + Validate the + + No create method that can create the + + + + Validate the for the and + + + + + Validate the for the given and + + The given + Dispose strategy is invalid for this and + + + + Creates and collects the s + + + + + The collected s + + + + + Add an Interface with a Type that implements it + + The Interface to add + The Type that implements the interface + The for this + The created + + + + Add an open generic Interface with an open generic Type that implements it + + The open generic Interface to add + The open generic Type that implements the interface + The for this + The created + Function can only be used to register open generic types + Can't register a multiton with open generic registration + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + A fourth interface to add + The that implements both interfaces + The for this + The created + + + + Add multiple interfaces for a that implements them + + The base interface to add + A second interface to add + A third interface to add + A fourth interface to add + A fifth interface to add + The that implements both interfaces + The for this + The created + + + + Add a without an interface + + The to add + The for this + The created + + + + Add an Interface with a Type that implements it as a multiton + + The Interface to add + The Type that implements the interface + The Type of the multiton scope + The created + + + + Add multiple interfaces for a that implements them as a multiton + + The base interface to add + A second interface to add + The Type that implements the interface + The Type of the multiton scope + The created + + + + Register all from an + + The of the first registered interface + The of the registered implementation + The + A factory to register interfaces and factories in an and create the needed s @@ -1640,6 +1783,11 @@ The The current instance of this + + + Validate the for the and + + An internal placeholder that is used to hold types that need to be resolved during the resolving process diff --git a/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs index 158f5cb..877c933 100644 --- a/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs +++ b/LightweightIocContainer/Registrations/MultipleMultitonRegistration.cs @@ -15,7 +15,7 @@ namespace LightweightIocContainer.Registrations /// The first interface /// The second interface /// The implementation - public class MultipleMultitonRegistration : MultitonRegistration, IMultipleMultitonRegistration where TImplementation : TInterface1, TInterface2 + internal class MultipleMultitonRegistration : MultitonRegistration, IMultipleMultitonRegistration where TImplementation : TInterface1, TInterface2 { /// /// An to register multiple interfaces for on implementation type that implements them as a multiton diff --git a/LightweightIocContainer/Registrations/MultipleRegistration.cs b/LightweightIocContainer/Registrations/MultipleRegistration.cs index b5ce902..9c3a3ae 100644 --- a/LightweightIocContainer/Registrations/MultipleRegistration.cs +++ b/LightweightIocContainer/Registrations/MultipleRegistration.cs @@ -14,7 +14,7 @@ namespace LightweightIocContainer.Registrations /// /// The first interface /// The implementation - public abstract class MultipleRegistration : TypedRegistration, IMultipleRegistration where TImplementation : TInterface1 + internal abstract class MultipleRegistration : TypedRegistration, IMultipleRegistration where TImplementation : TInterface1 { /// /// The base class for every to register multiple interfaces @@ -39,7 +39,7 @@ namespace LightweightIocContainer.Registrations /// The first interface /// The second interface /// The implementation - public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface1, TInterface2 + internal class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface1, TInterface2 { /// /// An to register multiple interfaces for on implementation type @@ -85,7 +85,7 @@ namespace LightweightIocContainer.Registrations /// The second interface /// The third interface /// The implementation - public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface3, TInterface2, TInterface1 + internal class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface3, TInterface2, TInterface1 { /// /// An to register multiple interfaces for on implementation type @@ -136,7 +136,7 @@ namespace LightweightIocContainer.Registrations /// The third interface /// The fourth interface /// The implementation - public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1 + internal class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1 { /// /// An to register multiple interfaces for on implementation type @@ -192,7 +192,7 @@ namespace LightweightIocContainer.Registrations /// The fourth interface /// The fifth interface /// The implementation - public class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1 + internal class MultipleRegistration : MultipleRegistration, IMultipleRegistration where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1 { /// /// An to register multiple interfaces for on implementation type diff --git a/LightweightIocContainer/Registrations/MultitonRegistration.cs b/LightweightIocContainer/Registrations/MultitonRegistration.cs index b2b7154..144833a 100644 --- a/LightweightIocContainer/Registrations/MultitonRegistration.cs +++ b/LightweightIocContainer/Registrations/MultitonRegistration.cs @@ -13,7 +13,7 @@ namespace LightweightIocContainer.Registrations /// /// The registered interface /// The registered implementation - public class MultitonRegistration : TypedRegistration, IMultitonRegistration where TImplementation : TInterface + internal class MultitonRegistration : TypedRegistration, IMultitonRegistration where TImplementation : TInterface { /// /// The registration that is used to register a multiton diff --git a/LightweightIocContainer/Registrations/OpenGenericRegistration.cs b/LightweightIocContainer/Registrations/OpenGenericRegistration.cs index 458233a..ed7d4de 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.Exceptions; using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Registrations; @@ -11,7 +12,7 @@ namespace LightweightIocContainer.Registrations /// /// for open generic types /// - public class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistration + internal class OpenGenericRegistration : RegistrationBase, IOpenGenericRegistration { /// /// for open generic types @@ -28,5 +29,19 @@ namespace LightweightIocContainer.Registrations /// The that implements the that is registered with this /// public Type ImplementationType { get; } + + /// + /// Validate this + /// + public override void Validate() + { + if (!InterfaceType.ContainsGenericParameters) + throw new InvalidRegistrationException("This function can only be used to register open generic types."); + + if (Lifestyle == Lifestyle.Multiton) + throw new InvalidRegistrationException("Can't register a multiton with open generic registration."); //TODO: Is there any need to register multitons with open generics? + + base.Validate(); + } } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/RegistrationBase.cs b/LightweightIocContainer/Registrations/RegistrationBase.cs index e1cffe8..842af64 100644 --- a/LightweightIocContainer/Registrations/RegistrationBase.cs +++ b/LightweightIocContainer/Registrations/RegistrationBase.cs @@ -17,7 +17,7 @@ namespace LightweightIocContainer.Registrations /// /// The that is used to register an Interface /// - public abstract class RegistrationBase : IRegistrationBase, IWithFactoryInternal, IWithParametersInternal, ILifestyleProvider + internal abstract class RegistrationBase : IRegistrationBase, IWithFactoryInternal, IWithParametersInternal, ILifestyleProvider, IWithDisposeStrategyInternal, IInternalValidationProvider { private readonly IocContainer _container; @@ -43,6 +43,11 @@ namespace LightweightIocContainer.Registrations /// The of Instances that are created with this /// public Lifestyle Lifestyle { get; } + + /// + /// The of singletons/multitons that implement and are created with this + /// + public DisposeStrategy DisposeStrategy { get; private set; } /// /// An of parameters that are used to an instance of this @@ -113,7 +118,6 @@ namespace LightweightIocContainer.Registrations TypedFactory factory = new(_container); Factory = factory; - ValidateFactory(); _container.RegisterFactory(factory); return this; @@ -128,17 +132,81 @@ namespace LightweightIocContainer.Registrations public IRegistrationBase WithFactory() where TFactoryImplementation : TFactoryInterface { Factory = new CustomTypedFactory(); - ValidateFactory(); - - _container.Register(); + _container.Register(r => r.Add()); return this; } + + /// + /// Add a for the + /// + /// The + /// The current instance of this + public IRegistrationBase WithDisposeStrategy(DisposeStrategy disposeStrategy) + { + DisposeStrategy = disposeStrategy; + return this; + } + + /// + /// Validate this + /// + public virtual void Validate() + { + ValidateMultiton(); + ValidateFactory(); + ValidateDisposeStrategy(); + } + /// + /// Validate that no registration that isn't derived from has + /// + /// + private void ValidateMultiton() + { + //don't allow lifestyle.multiton without iMultitonRegistration + if (Lifestyle == Lifestyle.Multiton && this is not IMultitonRegistration) + throw new InvalidRegistrationException("Can't register a type as Lifestyle.Multiton without a scope (Registration is not of type IMultitonRegistration)."); + } + + /// + /// Validate the + /// + /// No create method that can create the private void ValidateFactory() { - if (Factory?.CreateMethods.Any(c => c.ReturnType == InterfaceType) != true) + if (Factory == null) + return; + + if (Factory.CreateMethods.Any(c => c.ReturnType == InterfaceType) != true) throw new InvalidFactoryRegistrationException($"No create method that can create {InterfaceType}."); } + + /// + /// Validate the for the and + /// + protected virtual void ValidateDisposeStrategy() => ValidateDisposeStrategy(InterfaceType); + + /// + /// Validate the for the given and + /// + /// The given + /// Dispose strategy is invalid for this and + protected void ValidateDisposeStrategy(Type type) + { + if (Lifestyle == Lifestyle.Transient) + { + if (DisposeStrategy != DisposeStrategy.None) + throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle); + } + else + { + if (!type.IsAssignableTo(typeof(IDisposable))) + return; + + if (DisposeStrategy == DisposeStrategy.None) + throw new InvalidDisposeStrategyException(DisposeStrategy, type, Lifestyle); + } + } } } \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/RegistrationCollector.cs b/LightweightIocContainer/Registrations/RegistrationCollector.cs new file mode 100644 index 0000000..3d1fa94 --- /dev/null +++ b/LightweightIocContainer/Registrations/RegistrationCollector.cs @@ -0,0 +1,188 @@ +// Author: Gockner, Simon +// Created: 2021-12-15 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; +using System.Collections.Generic; +using LightweightIocContainer.Exceptions; +using LightweightIocContainer.Interfaces.Registrations; + +namespace LightweightIocContainer.Registrations; + +/// +/// Creates and collects the s +/// +public class RegistrationCollector : IRegistrationCollector +{ + private readonly RegistrationFactory _registrationFactory; + + internal RegistrationCollector(RegistrationFactory registrationFactory) + { + _registrationFactory = registrationFactory; + Registrations = new List(); + } + + /// + /// The collected s + /// + internal List Registrations { get; } + + /// + /// Add an Interface with a Type that implements it + /// + /// The Interface to add + /// The Type that implements the interface + /// The for this + /// The created + public ITypedRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface + { + ITypedRegistration registration = _registrationFactory.Register(lifestyle); + Registrations.Add(registration); + + return registration; + } + + /// + /// Add an open generic Interface with an open generic Type that implements it + /// + /// The open generic Interface to add + /// The open generic Type that implements the interface + /// The for this + /// The created + /// Function can only be used to register open generic types + /// Can't register a multiton with open generic registration + public IOpenGenericRegistration AddOpenGenerics(Type tInterface, Type tImplementation, Lifestyle lifestyle = Lifestyle.Transient) + { + IOpenGenericRegistration registration = _registrationFactory.Register(tInterface, tImplementation, lifestyle); + Registrations.Add(registration); + + return registration; + } + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// The that implements both interfaces + /// The for this + /// The created + public IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface2, TInterface1 + { + IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); + Register(multipleRegistration); + + return multipleRegistration; + } + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// The that implements both interfaces + /// The for this + /// The created + public IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface3, TInterface2, TInterface1 + { + IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); + Register(multipleRegistration); + + return multipleRegistration; + } + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// A fourth interface to add + /// The that implements both interfaces + /// The for this + /// The created + public IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface4, TInterface3, TInterface2, TInterface1 + { + IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); + Register(multipleRegistration); + + return multipleRegistration; + } + + /// + /// Add multiple interfaces for a that implements them + /// + /// The base interface to add + /// A second interface to add + /// A third interface to add + /// A fourth interface to add + /// A fifth interface to add + /// The that implements both interfaces + /// The for this + /// The created + public IMultipleRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface5, TInterface4, TInterface3, TInterface2, TInterface1 + { + IMultipleRegistration multipleRegistration = _registrationFactory.Register(lifestyle); + Register(multipleRegistration); + + return multipleRegistration; + } + + /// + /// Add a without an interface + /// + /// The to add + /// The for this + /// The created + public ISingleTypeRegistration Add(Lifestyle lifestyle = Lifestyle.Transient) + { + ISingleTypeRegistration registration = _registrationFactory.Register(lifestyle); + Registrations.Add(registration); + + return registration; + } + + /// + /// Add an Interface with a Type that implements it as a multiton + /// + /// The Interface to add + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + public IMultitonRegistration AddMultiton() where TImplementation : TInterface + { + IMultitonRegistration registration = _registrationFactory.RegisterMultiton(); + Registrations.Add(registration); + + return registration; + } + + /// + /// Add multiple interfaces for a that implements them as a multiton + /// + /// The base interface to add + /// A second interface to add + /// The Type that implements the interface + /// The Type of the multiton scope + /// The created + public IMultipleMultitonRegistration AddMultiton() where TImplementation : TInterface1, TInterface2 + { + IMultipleMultitonRegistration registration = _registrationFactory.RegisterMultiton(); + Register(registration); + + return registration; + } + + /// + /// Register all from an + /// + /// The of the first registered interface + /// The of the registered implementation + /// The + private void Register(IMultipleRegistration multipleRegistration) where TImplementation : TInterface1 + { + foreach (IRegistration registration in multipleRegistration.Registrations) + Registrations.Add(registration); + } +} \ No newline at end of file diff --git a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs index ed36d70..2f31602 100644 --- a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs +++ b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs @@ -12,7 +12,7 @@ namespace LightweightIocContainer.Registrations /// The to register either only an interface or only a /// /// The of the - public class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration + internal class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration { /// /// The to register either only an interface or only a diff --git a/LightweightIocContainer/Registrations/TypedRegistration.cs b/LightweightIocContainer/Registrations/TypedRegistration.cs index dc6d73d..344059d 100644 --- a/LightweightIocContainer/Registrations/TypedRegistration.cs +++ b/LightweightIocContainer/Registrations/TypedRegistration.cs @@ -13,7 +13,7 @@ namespace LightweightIocContainer.Registrations /// /// A that implements a /// - public class TypedRegistration : RegistrationBase, ITypedRegistration where TImplementation : TInterface + internal class TypedRegistration : RegistrationBase, ITypedRegistration where TImplementation : TInterface { /// /// A that implements a @@ -53,5 +53,10 @@ namespace LightweightIocContainer.Registrations OnCreateAction = a => action((TImplementation?) a); return this; } + + /// + /// Validate the for the and + /// + protected override void ValidateDisposeStrategy() => ValidateDisposeStrategy(ImplementationType); } } \ No newline at end of file diff --git a/Test.LightweightIocContainer/AssemblyInstallerTest.cs b/Test.LightweightIocContainer/AssemblyInstallerTest.cs index df0a09b..15fa82d 100644 --- a/Test.LightweightIocContainer/AssemblyInstallerTest.cs +++ b/Test.LightweightIocContainer/AssemblyInstallerTest.cs @@ -22,7 +22,7 @@ namespace Test.LightweightIocContainer [UsedImplicitly] public class TestInstaller : IIocInstaller { - public void Install(IIocContainer container) => container.Register>(); + public void Install(IRegistrationCollector registration) => registration.Add>(); } [UsedImplicitly] @@ -44,12 +44,12 @@ namespace Test.LightweightIocContainer Mock assemblyMock = new(); assemblyMock.Setup(a => a.GetTypes()).Returns(types.ToArray); - Mock iocContainerMock = new(); + Mock registrationCollectorMock = new(); AssemblyInstaller assemblyInstaller = new(assemblyMock.Object); - assemblyInstaller.Install(iocContainerMock.Object); + assemblyInstaller.Install(registrationCollectorMock.Object); - iocContainerMock.Verify(ioc => ioc.Register>>(It.IsAny()), Times.Once); + registrationCollectorMock.Verify(r => r.Add>>(It.IsAny()), Times.Once); } [Test] diff --git a/Test.LightweightIocContainer/DisposeStrategyTest.cs b/Test.LightweightIocContainer/DisposeStrategyTest.cs new file mode 100644 index 0000000..7f2cdb9 --- /dev/null +++ b/Test.LightweightIocContainer/DisposeStrategyTest.cs @@ -0,0 +1,91 @@ +// Author: Gockner, Simon +// Created: 2021-12-16 +// Copyright(c) 2021 SimonG. All Rights Reserved. + +using System; +using JetBrains.Annotations; +using LightweightIocContainer; +using LightweightIocContainer.Exceptions; +using NUnit.Framework; + +namespace Test.LightweightIocContainer; + +[TestFixture] +public class DisposeStrategyTest +{ + [UsedImplicitly] + public interface ITest : IDisposable + { + + } + + private class Test : ITest + { + public void Dispose() => throw new Exception(); + } + + [Test] + public void TestValidContainerDisposeStrategySingleton() + { + IocContainer iocContainer = new(); + iocContainer.Register(r => r.Add(Lifestyle.Singleton).WithDisposeStrategy(DisposeStrategy.Container)); + + iocContainer.Resolve(); + + Assert.Throws(() => iocContainer.Dispose()); + } + + [Test] + public void TestValidContainerDisposeStrategyMultiton() + { + IocContainer iocContainer = new(); + iocContainer.Register(r => r.AddMultiton().WithDisposeStrategy(DisposeStrategy.Container)); + + iocContainer.Resolve(1); + + Assert.Throws(() => iocContainer.Dispose()); + } + + [Test] + public void TestValidAppDisposeStrategySingleton() + { + IocContainer iocContainer = new(); + iocContainer.Register(r => r.Add(Lifestyle.Singleton).WithDisposeStrategy(DisposeStrategy.Application)); + + iocContainer.Resolve(); + + Assert.DoesNotThrow(() => iocContainer.Dispose()); + } + + [Test] + public void TestValidAppDisposeStrategyMultiton() + { + IocContainer iocContainer = new(); + iocContainer.Register(r => r.AddMultiton().WithDisposeStrategy(DisposeStrategy.Application)); + + iocContainer.Resolve(1); + + Assert.DoesNotThrow(() => iocContainer.Dispose()); + } + + [Test] + public void TestInvalidDisposeStrategySingleton() + { + IocContainer iocContainer = new(); + Assert.Throws(() => iocContainer.Register(r => r.Add(Lifestyle.Singleton))); + } + + [Test] + public void TestInvalidDisposeStrategyMultiton() + { + IocContainer iocContainer = new(); + Assert.Throws(() => iocContainer.Register(r => r.AddMultiton())); + } + + [Test] + public void TestInvalidDisposeStrategyTransient() + { + IocContainer iocContainer = new(); + Assert.Throws(() => iocContainer.Register(r => r.Add().WithDisposeStrategy(DisposeStrategy.Container))); + } +} \ No newline at end of file diff --git a/Test.LightweightIocContainer/EnumerableExtensionTest.cs b/Test.LightweightIocContainer/EnumerableExtensionTest.cs index c4d8578..95e0d3c 100644 --- a/Test.LightweightIocContainer/EnumerableExtensionTest.cs +++ b/Test.LightweightIocContainer/EnumerableExtensionTest.cs @@ -4,7 +4,9 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; +using JetBrains.Annotations; using LightweightIocContainer; +using Moq; using NUnit.Framework; namespace Test.LightweightIocContainer @@ -22,6 +24,12 @@ namespace Test.LightweightIocContainer } + [UsedImplicitly] + public interface ITest + { + void DoSomething(); + } + [Test] [SuppressMessage("ReSharper", "CollectionNeverUpdated.Local")] @@ -72,5 +80,23 @@ namespace Test.LightweightIocContainer Assert.IsNotInstanceOf(listObject); Assert.AreEqual(2, listObject.Index); } + + [Test] + public void TestForEach() + { + Mock test1 = new(); + Mock test2 = new(); + Mock test3 = new(); + Mock test4 = new(); + + IEnumerable enumerable = new[] { test1.Object, test2.Object, test3.Object, test4.Object }; + + enumerable.ForEach(t => t.DoSomething()); + + test1.Verify(t => t.DoSomething(), Times.Once); + test2.Verify(t => t.DoSomething(), Times.Once); + test3.Verify(t => t.DoSomething(), Times.Once); + test4.Verify(t => t.DoSomething(), Times.Once); + } } } \ No newline at end of file diff --git a/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs index efb88a0..9535138 100644 --- a/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs +++ b/Test.LightweightIocContainer/FluentFactoryRegistrationTest.cs @@ -100,7 +100,7 @@ namespace Test.LightweightIocContainer [Test] public void TestFluentFactoryRegistration() { - _iocContainer.Register().WithFactory(); + _iocContainer.Register(r => r.Add().WithFactory()); ITestFactory factory = _iocContainer.Resolve(); ITest test = _iocContainer.Resolve(); @@ -112,7 +112,7 @@ namespace Test.LightweightIocContainer [Test] public void TestFluentFactoryRegistration_CustomFactory() { - _iocContainer.Register().WithFactory(); + _iocContainer.Register(r => r.Add().WithFactory()); ITestFactory factory = _iocContainer.Resolve(); ITest test = _iocContainer.Resolve(); @@ -122,15 +122,15 @@ namespace Test.LightweightIocContainer } [Test] - public void TestRegisterFactoryWithoutCreate() => Assert.Throws(() => _iocContainer.Register().WithFactory()); + public void TestRegisterFactoryWithoutCreate() => Assert.Throws(() => _iocContainer.Register(r => r.Add().WithFactory())); [Test] - public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws(() => _iocContainer.Register().WithFactory()); + public void TestRegisterFactoryClearMultitonsNonGeneric() => Assert.Throws(() => _iocContainer.Register(r => r.Add().WithFactory())); [Test] public void TestResolveFromFactory() { - _iocContainer.Register().WithFactory(); + _iocContainer.Register(r => r.Add().WithFactory()); ITestFactory testFactory = _iocContainer.Resolve(); ITest createdTest = testFactory.Create(); @@ -141,8 +141,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveFromFactoryWithParams() { - _iocContainer.Register().WithFactory(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + _iocContainer.Register(r => r.Add().WithFactory()); + _iocContainer.Register(r => r.Add()); //this registration is abnormal and should only be used in unit tests ITestFactory testFactory = _iocContainer.Resolve(); ITest createdTest = testFactory.Create("Test"); @@ -153,8 +153,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveFromFactoryWithDefaultParamCreate() { - _iocContainer.Register().WithFactory(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + _iocContainer.Register(r => r.Add().WithFactory()); + _iocContainer.Register(r => r.Add()); //this registration is abnormal and should only be used in unit tests ITestFactory testFactory = _iocContainer.Resolve(); ITest createdTest = testFactory.CreateTest(); @@ -165,8 +165,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveFromFactoryWithDefaultParamCtor() { - _iocContainer.Register().WithFactory(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + _iocContainer.Register(r => r.Add().WithFactory()); + _iocContainer.Register(r => r.Add()); //this registration is abnormal and should only be used in unit tests ITestFactory testFactory = _iocContainer.Resolve(); ITest createdTest = testFactory.Create(); @@ -177,7 +177,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveFromFactoryWithByte() { - _iocContainer.Register().WithFactory(); + _iocContainer.Register(r => r.Add().WithFactory()); ITestFactory testFactory = _iocContainer.Resolve(); ITest createdTest = testFactory.Create(1); @@ -188,7 +188,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveMultitonFromFactory() { - _iocContainer.RegisterMultiton().WithFactory(); + _iocContainer.Register(r => r.AddMultiton().WithFactory()); MultitonScope scope1 = new(); MultitonScope scope2 = new(); @@ -207,7 +207,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveMultitonFromFactoryClearInstances() { - _iocContainer.RegisterMultiton().WithFactory(); + _iocContainer.Register(r => r.AddMultiton().WithFactory()); MultitonScope scope1 = new(); MultitonScope scope2 = new(); @@ -234,6 +234,6 @@ namespace Test.LightweightIocContainer [Test] public void TestInvalidCreateMethodReturnType() => - Assert.Throws(() => _iocContainer.Register().WithFactory()); + Assert.Throws(() => _iocContainer.Register(r => r.Add().WithFactory())); } } \ No newline at end of file diff --git a/Test.LightweightIocContainer/IocContainerInterfaceSegregationTest.cs b/Test.LightweightIocContainer/IocContainerInterfaceSegregationTest.cs index e93056a..bc4e939 100644 --- a/Test.LightweightIocContainer/IocContainerInterfaceSegregationTest.cs +++ b/Test.LightweightIocContainer/IocContainerInterfaceSegregationTest.cs @@ -54,7 +54,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegistrationOnCreate2() { - _container.Register().OnCreate(foo => foo.ThrowFoo()); + _container.Register(r => r.Add().OnCreate(foo => foo.ThrowFoo())); Exception fooException = Assert.Throws(() => _container.Resolve()); Assert.AreEqual("Foo", fooException?.Message); @@ -66,7 +66,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegistrationOnCreate3() { - _container.Register().OnCreate(foo => foo.ThrowFoo()); + _container.Register(r => r.Add().OnCreate(foo => foo.ThrowFoo())); Exception fooException = Assert.Throws(() => _container.Resolve()); Assert.AreEqual("Foo", fooException?.Message); @@ -81,7 +81,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegistrationOnCreate4() { - _container.Register().OnCreate(foo => foo.ThrowFoo()); + _container.Register(r => r.Add().OnCreate(foo => foo.ThrowFoo())); Exception fooException = Assert.Throws(() => _container.Resolve()); Assert.AreEqual("Foo", fooException?.Message); @@ -99,7 +99,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegistrationOnCreate5() { - _container.Register().OnCreate(foo => foo.ThrowFoo()); + _container.Register(r => r.Add().OnCreate(foo => foo.ThrowFoo())); Exception fooException = Assert.Throws(() => _container.Resolve()); Assert.AreEqual("Foo", fooException?.Message); @@ -120,7 +120,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveTransient() { - _container.Register(); + _container.Register(r => r.Add()); IFoo foo = _container.Resolve(); IBar bar = _container.Resolve(); IAnotherFoo anotherFoo = _container.Resolve(); @@ -137,7 +137,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveSingleton() { - _container.Register(Lifestyle.Singleton); + _container.Register(r => r.Add(Lifestyle.Singleton)); IFoo foo = _container.Resolve(); IBar bar = _container.Resolve(); IAnotherFoo anotherFoo = _container.Resolve(); diff --git a/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs b/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs index b3c6bee..481964f 100644 --- a/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs +++ b/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs @@ -101,7 +101,7 @@ namespace Test.LightweightIocContainer IC c = new C(); IB b = new B(c); - _iocContainer.Register().WithParameters(b, c); + _iocContainer.Register(r => r.Add().WithParameters(b, c)); IA a = _iocContainer.Resolve(); Assert.AreEqual(b, a.B); @@ -114,7 +114,7 @@ namespace Test.LightweightIocContainer IC c = new C(); IB b = new B(c); - _iocContainer.Register().WithParameters(b); + _iocContainer.Register(r => r.Add().WithParameters(b)); IA a = _iocContainer.Resolve(c); Assert.AreEqual(b, a.B); @@ -129,7 +129,7 @@ namespace Test.LightweightIocContainer IA a = new A(b, c); IA a2 = new A(b, c); - _iocContainer.Register().WithParameters((0, a), (2, b), (3, c)); + _iocContainer.Register(r => r.Add().WithParameters((0, a), (2, b), (3, c))); ID d = _iocContainer.Resolve(a2); Assert.AreEqual(a, d.A); @@ -146,9 +146,9 @@ namespace Test.LightweightIocContainer IA a = new A(b, c); IA a2 = new A(b, c); - _iocContainer.Register().WithParameters(a2); - _iocContainer.Register(); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add().WithParameters(a2)); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); ID d = _iocContainer.Resolve(a); diff --git a/Test.LightweightIocContainer/IocContainerRecursionTest.cs b/Test.LightweightIocContainer/IocContainerRecursionTest.cs index 7f480e0..1e0c67d 100644 --- a/Test.LightweightIocContainer/IocContainerRecursionTest.cs +++ b/Test.LightweightIocContainer/IocContainerRecursionTest.cs @@ -110,8 +110,8 @@ namespace Test.LightweightIocContainer [Test] public void TestCircularDependencies() { - _iocContainer.Register(); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); NoMatchingConstructorFoundException noMatchingConstructorFoundException = Assert.Throws(() => _iocContainer.Resolve()); ConstructorNotMatchingException fooConstructorNotMatchingException = (ConstructorNotMatchingException) noMatchingConstructorFoundException?.InnerExceptions[0]; @@ -145,9 +145,9 @@ namespace Test.LightweightIocContainer [Test] public void TestNonCircularDependencies() { - _iocContainer.Register(); - _iocContainer.Register(); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); IA a = _iocContainer.Resolve(); Assert.IsNotNull(a); @@ -156,8 +156,8 @@ namespace Test.LightweightIocContainer [Test] public void TestRecursionWithParam() { - _iocContainer.Register(); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); Assert.DoesNotThrow(() => _iocContainer.Resolve(new Mock().Object)); Assert.DoesNotThrow(() => _iocContainer.Resolve(new Mock().Object)); @@ -166,8 +166,8 @@ namespace Test.LightweightIocContainer [Test] public void TestNonCircularCrossDependencies() { - _iocContainer.Register(); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); Assert.DoesNotThrow(() => _iocContainer.Resolve()); Assert.DoesNotThrow(() => _iocContainer.Resolve()); diff --git a/Test.LightweightIocContainer/IocContainerTest.cs b/Test.LightweightIocContainer/IocContainerTest.cs index 444c666..6c92ac2 100644 --- a/Test.LightweightIocContainer/IocContainerTest.cs +++ b/Test.LightweightIocContainer/IocContainerTest.cs @@ -3,6 +3,7 @@ using LightweightIocContainer; using LightweightIocContainer.Exceptions; using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Installers; +using LightweightIocContainer.Interfaces.Registrations; using Moq; using NUnit.Framework; @@ -111,7 +112,7 @@ namespace Test.LightweightIocContainer Mock installerMock = new(); IIocContainer returnedContainer = _iocContainer.Install(installerMock.Object); - installerMock.Verify(m => m.Install(It.IsAny()), Times.Once); + installerMock.Verify(m => m.Install(It.IsAny()), Times.Once); Assert.AreEqual(_iocContainer, returnedContainer); } @@ -125,30 +126,30 @@ namespace Test.LightweightIocContainer IIocContainer returnedContainer = _iocContainer.Install(installer1Mock.Object, installer2Mock.Object, installer3Mock.Object); - installer1Mock.Verify(m => m.Install(It.IsAny()), Times.Once); - installer2Mock.Verify(m => m.Install(It.IsAny()), Times.Once); - installer3Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + installer1Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + installer2Mock.Verify(m => m.Install(It.IsAny()), Times.Once); + installer3Mock.Verify(m => m.Install(It.IsAny()), Times.Once); Assert.AreEqual(_iocContainer, returnedContainer); } [Test] - public void TestRegister() => Assert.DoesNotThrow(() => _iocContainer.Register()); + public void TestRegister() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add())); [Test] - public void TestRegisterTypeWithoutInterface() => Assert.DoesNotThrow(() => _iocContainer.Register()); + public void TestRegisterTypeWithoutInterface() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.Add())); [Test] - public void TestRegisterMultiton() => Assert.DoesNotThrow(() => _iocContainer.RegisterMultiton()); + public void TestRegisterMultiton() => Assert.DoesNotThrow(() => _iocContainer.Register(r => r.AddMultiton())); [Test] - public void TestInvalidMultitonRegistration() => Assert.Throws(() => _iocContainer.Register(Lifestyle.Multiton)); + public void TestInvalidMultitonRegistration() => Assert.Throws(() => _iocContainer.Register(r => r.Add(Lifestyle.Multiton))); [Test] public void TestRegisterMultiple() { - _iocContainer.Register(); - MultipleRegistrationException exception = Assert.Throws(() => _iocContainer.Register()); + _iocContainer.Register(r => r.Add()); + MultipleRegistrationException exception = Assert.Throws(() => _iocContainer.Register(r => r.Add())); Assert.AreEqual(typeof(ITest), exception?.Type); } @@ -162,7 +163,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolve() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); ITest resolvedTest = _iocContainer.Resolve(); @@ -172,7 +173,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveWithoutInterface() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Test resolvedTest = _iocContainer.Resolve(); @@ -182,14 +183,14 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveInterfaceWithoutImplementation() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Assert.Throws(() => _iocContainer.Resolve()); } [Test] public void TestResolveImplementationRegisteredWithInterface() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Test resolvedTest = _iocContainer.Resolve(); @@ -199,7 +200,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveWithParams() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); ITest resolvedTest = _iocContainer.Resolve("Test", new Test()); @@ -209,8 +210,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveWithMissingParam() { - _iocContainer.Register(); - _iocContainer.Register(); //this registration is abnormal and should only be used in unit tests + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add()); //this registration is abnormal and should only be used in unit tests ITest resolvedTest = _iocContainer.Resolve("Test"); @@ -220,7 +221,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveSingleton() { - _iocContainer.Register(Lifestyle.Singleton); + _iocContainer.Register(r => r.Add(Lifestyle.Singleton)); ITest resolvedTest = _iocContainer.Resolve(); ITest secondResolvedTest = _iocContainer.Resolve(); @@ -231,7 +232,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveMultiton() { - _iocContainer.RegisterMultiton(); + _iocContainer.Register(r => r.AddMultiton()); MultitonScope scope1 = new(); MultitonScope scope2 = new(); @@ -248,7 +249,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveMultitonNoArgs() { - _iocContainer.RegisterMultiton(); + _iocContainer.Register(r => r.AddMultiton()); MultitonResolveException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(ITest), exception?.Type); @@ -257,7 +258,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveMultitonWrongArgs() { - _iocContainer.RegisterMultiton(); + _iocContainer.Register(r => r.AddMultiton()); MultitonResolveException exception = Assert.Throws(() => _iocContainer.Resolve(new object())); Assert.AreEqual(typeof(ITest), exception?.Type); @@ -266,7 +267,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveTransient() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); ITest resolvedTest = _iocContainer.Resolve(); ITest secondResolvedTest = _iocContainer.Resolve(); @@ -277,7 +278,7 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveNoMatchingConstructor() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); NoMatchingConstructorFoundException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(TestConstructor), exception?.Type); } @@ -285,14 +286,14 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveNoMatchingConstructorNotThrownWrongly() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Assert.DoesNotThrow(() => _iocContainer.Resolve("Name")); } [Test] public void TestResolvePrivateConstructor() { - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); NoPublicConstructorFoundException exception = Assert.Throws(() => _iocContainer.Resolve()); Assert.AreEqual(typeof(TestPrivateConstructor), exception?.Type); } @@ -300,8 +301,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveSingleTypeRegistrationWithFactoryMethod() { - _iocContainer.Register(); - _iocContainer.Register().WithFactoryMethod(c => new TestConstructor(c.Resolve(), "someName")); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add().WithFactoryMethod(c => new TestConstructor(c.Resolve(), "someName"))); ITest test = _iocContainer.Resolve(); @@ -311,8 +312,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveParameterIsRegisteredWithParameters() { - _iocContainer.Register(); - _iocContainer.Register().WithParameters("TestString"); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add().WithParameters("TestString")); ITest test = _iocContainer.Resolve("testName"); @@ -322,8 +323,8 @@ namespace Test.LightweightIocContainer [Test] public void TestResolveParameterWithParameterThatIsAlreadyExistingSingleton() { - _iocContainer.Register(); - _iocContainer.Register(Lifestyle.Singleton).WithParameters("TestString"); + _iocContainer.Register(r => r.Add()); + _iocContainer.Register(r => r.Add(Lifestyle.Singleton).WithParameters("TestString")); IFoo foo = _iocContainer.Resolve(); ITest test = _iocContainer.Resolve("testName"); @@ -337,10 +338,10 @@ namespace Test.LightweightIocContainer { Assert.False(_iocContainer.IsTypeRegistered()); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Assert.True(_iocContainer.IsTypeRegistered()); - _iocContainer.Register(); + _iocContainer.Register(r => r.Add()); Assert.True(_iocContainer.IsTypeRegistered()); } } diff --git a/Test.LightweightIocContainer/IocValidatorTest.cs b/Test.LightweightIocContainer/IocValidatorTest.cs index a79ed89..818e8bd 100644 --- a/Test.LightweightIocContainer/IocValidatorTest.cs +++ b/Test.LightweightIocContainer/IocValidatorTest.cs @@ -6,8 +6,8 @@ using System; using JetBrains.Annotations; using LightweightIocContainer; using LightweightIocContainer.Exceptions; -using LightweightIocContainer.Interfaces; using LightweightIocContainer.Interfaces.Installers; +using LightweightIocContainer.Interfaces.Registrations; using LightweightIocContainer.Validation; using Moq; using NUnit.Framework; @@ -47,12 +47,12 @@ namespace Test.LightweightIocContainer private class TestInstaller : IIocInstaller { - public void Install(IIocContainer container) => container.Register().WithFactory(); + public void Install(IRegistrationCollector registration) => registration.Add().WithFactory(); } private class InvalidTestInstaller : IIocInstaller { - public void Install(IIocContainer container) => container.Register().WithFactory(); + public void Install(IRegistrationCollector registration) => registration.Add().WithFactory(); } [Test] diff --git a/Test.LightweightIocContainer/MultiLayerResolveTest.cs b/Test.LightweightIocContainer/MultiLayerResolveTest.cs index 8309840..3c7d857 100644 --- a/Test.LightweightIocContainer/MultiLayerResolveTest.cs +++ b/Test.LightweightIocContainer/MultiLayerResolveTest.cs @@ -64,8 +64,8 @@ public class MultiLayerResolveTest public void TestResolveFactoryAsCtorParameter() { IocContainer container = new(); - container.Register().WithFactory(); - container.Register().WithFactory(); + container.Register(r => r.Add().WithFactory()); + container.Register(r => r.Add().WithFactory()); IA a = container.Resolve(); Assert.IsInstanceOf(a); @@ -75,9 +75,9 @@ public class MultiLayerResolveTest public void TestResolveSingleTypeRegistrationAsCtorParameter() { IocContainer container = new(); - container.Register(); - container.Register().WithFactory(); - container.Register().WithFactoryMethod(_ => new C("test")); + container.Register(r => r.Add()); + container.Register(r => r.Add().WithFactory()); + container.Register(r => r.Add().WithFactoryMethod(_ => new C("test"))); IB b = container.Resolve(); Assert.IsInstanceOf(b); diff --git a/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs b/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs index 5328fee..b346a27 100644 --- a/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs +++ b/Test.LightweightIocContainer/MultipleMultitonRegistrationTest.cs @@ -48,7 +48,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegisterAndResolveMultipleMultitonRegistration() { - _iocContainer.RegisterMultiton(); + _iocContainer.Register(r => r.AddMultiton()); MultitonScope scope = new(); @@ -64,7 +64,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegisterAndResolveMultipleMultitonRegistrationWithDifferentScope() { - _iocContainer.RegisterMultiton(); + _iocContainer.Register(r => r.AddMultiton()); MultitonScope scope = new(); MultitonScope differentScope = new(); @@ -82,7 +82,7 @@ namespace Test.LightweightIocContainer [Test] public void TestMultipleMultitonRegistrationOnCreate() { - _iocContainer.RegisterMultiton().OnCreate(t => t.DoSomething(1)); + _iocContainer.Register(r => r.AddMultiton().OnCreate(t => t.DoSomething(1))); MultitonScope scope = new(); diff --git a/Test.LightweightIocContainer/OnCreateTest.cs b/Test.LightweightIocContainer/OnCreateTest.cs index ef7816c..8e00c81 100644 --- a/Test.LightweightIocContainer/OnCreateTest.cs +++ b/Test.LightweightIocContainer/OnCreateTest.cs @@ -31,9 +31,9 @@ namespace Test.LightweightIocContainer RegistrationFactory registrationFactory = new(new Mock().Object); ITypedRegistration testRegistration = registrationFactory.Register(Lifestyle.Transient).OnCreate(t => t.DoSomething()); - Test test = new Test(); + Test test = new(); - Assert.Throws(() => testRegistration.OnCreateAction(test)); + Assert.Throws(() => testRegistration.OnCreateAction!(test)); } } } \ No newline at end of file diff --git a/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs b/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs index 50425c1..bd880bf 100644 --- a/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs +++ b/Test.LightweightIocContainer/OpenGenericRegistrationTest.cs @@ -37,7 +37,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegisterOpenGenericType() { - _iocContainer.RegisterOpenGenerics(typeof(ITest<>), typeof(Test<>)); + _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>))); ITest test = _iocContainer.Resolve>(); Assert.NotNull(test); @@ -46,7 +46,7 @@ namespace Test.LightweightIocContainer [Test] public void TestRegisterOpenGenericTypeAsSingleton() { - _iocContainer.RegisterOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton); + _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Singleton)); ITest test = _iocContainer.Resolve>(); Assert.NotNull(test); @@ -60,10 +60,10 @@ namespace Test.LightweightIocContainer [Test] public void TestRegisterOpenGenericTypeAsMultitonThrowsException() => - Assert.Throws(() => _iocContainer.RegisterOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Multiton)); + Assert.Throws(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(ITest<>), typeof(Test<>), Lifestyle.Multiton))); [Test] public void TestRegisterNonOpenGenericTypeWithOpenGenericsFunctionThrowsException() => - Assert.Throws(() => _iocContainer.RegisterOpenGenerics(typeof(int), typeof(int))); + Assert.Throws(() => _iocContainer.Register(r => r.AddOpenGenerics(typeof(int), typeof(int)))); } } \ No newline at end of file diff --git a/Test.LightweightIocContainer/RegistrationBaseTest.cs b/Test.LightweightIocContainer/RegistrationBaseTest.cs index 6776230..e5ed34f 100644 --- a/Test.LightweightIocContainer/RegistrationBaseTest.cs +++ b/Test.LightweightIocContainer/RegistrationBaseTest.cs @@ -60,7 +60,7 @@ namespace Test.LightweightIocContainer RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register(Lifestyle.Transient).WithParameters(bar, test); - Assert.AreEqual(bar, testRegistration.Parameters[0]); + Assert.AreEqual(bar, testRegistration.Parameters![0]); Assert.AreEqual(test, testRegistration.Parameters[1]); } @@ -74,7 +74,7 @@ namespace Test.LightweightIocContainer RegistrationBase testRegistration = (RegistrationBase) registrationFactory.Register(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString")); - Assert.AreEqual(bar, testRegistration.Parameters[0]); + Assert.AreEqual(bar, testRegistration.Parameters![0]); Assert.IsInstanceOf(testRegistration.Parameters[1]); Assert.AreEqual("SomeString", testRegistration.Parameters[2]); Assert.AreEqual(test, testRegistration.Parameters[3]); diff --git a/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs index 2acc5bc..a80eff8 100644 --- a/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs +++ b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs @@ -50,17 +50,17 @@ namespace Test.LightweightIocContainer RegistrationFactory registrationFactory = new(iocContainerMock.Object); ISingleTypeRegistration registration = registrationFactory.Register(Lifestyle.Transient).WithFactoryMethod(c => new Foo(c.Resolve())); - IFoo foo = registration.FactoryMethod(iocContainerMock.Object); + IFoo foo = registration.FactoryMethod!(iocContainerMock.Object); Assert.AreEqual(bar, foo.Bar); } [Test] public void TestSingleTypeRegistrationResolveSingleton() { - IocContainer container = new IocContainer(); + IocContainer container = new(); IBar bar = new Bar(); - container.Register(Lifestyle.Singleton).WithFactoryMethod(_ => new Foo(bar)); + container.Register(r => r.Add(Lifestyle.Singleton).WithFactoryMethod(_ => new Foo(bar))); IFoo foo = container.Resolve();