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