diff --git a/LightweightIocContainer/Exceptions/UnknownRegistrationException.cs b/LightweightIocContainer/Exceptions/UnknownRegistrationException.cs
index 0a83286..50b25c2 100644
--- a/LightweightIocContainer/Exceptions/UnknownRegistrationException.cs
+++ b/LightweightIocContainer/Exceptions/UnknownRegistrationException.cs
@@ -8,12 +8,12 @@ using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Exceptions
{
///
- /// An unknown was used
+ /// An unknown was used
///
internal class UnknownRegistrationException : Exception
{
///
- /// An unknown was used
+ /// An unknown was used
///
/// The exception message
public UnknownRegistrationException(string message)
diff --git a/LightweightIocContainer/Interfaces/IIocContainer.cs b/LightweightIocContainer/Interfaces/IIocContainer.cs
index afa8af9..0b5d2bd 100644
--- a/LightweightIocContainer/Interfaces/IIocContainer.cs
+++ b/LightweightIocContainer/Interfaces/IIocContainer.cs
@@ -3,14 +3,13 @@
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
-using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Interfaces
{
///
- /// The main container that carries all the s and can resolve all the types you'll ever want
+ /// The main container that carries all the s and can resolve all the types you'll ever want
///
public interface IIocContainer : IDisposable
{
@@ -26,17 +25,17 @@ namespace LightweightIocContainer.Interfaces
///
/// The Interface to register
/// The Type that implements the interface
- /// The for this
- /// The created
+ /// The for this
+ /// The created
IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface;
///
/// Register a without an interface
///
/// The to register
- /// The for this
- /// The created
- IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient);
+ /// The for this
+ /// The created
+ ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient);
///
/// Register an Interface with a Type that implements it as a multiton
@@ -44,14 +43,14 @@ namespace LightweightIocContainer.Interfaces
/// The Interface to register
/// The Type that implements the interface
/// The Type of the multiton scope
- /// The created
+ /// The created
IMultitonRegistration Register() where TImplementation : TInterface;
///
/// Register an Interface as an abstract typed factory
///
/// The abstract typed factory to register
- /// The created
+ /// The created
ITypedFactoryRegistration RegisterFactory();
///
@@ -59,7 +58,8 @@ namespace LightweightIocContainer.Interfaces
///
/// The Interface to register
/// The for the callback
- /// The created
+ /// The created
+ [Obsolete("RegisterUnitTestCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
IUnitTestCallbackRegistration RegisterUnitTestCallback(ResolveCallback unitTestCallback);
///
diff --git a/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs b/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs
index fb99ce6..d329bd4 100644
--- a/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs
+++ b/LightweightIocContainer/Interfaces/Installers/IIocInstaller.cs
@@ -12,7 +12,7 @@ namespace LightweightIocContainer.Interfaces.Installers
public interface IIocInstaller
{
///
- /// Install the needed s in the given
+ /// Install the needed s in the given
///
/// The current
void Install(IIocContainer container);
diff --git a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs
index 6c57fd4..3597927 100644
--- a/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs
+++ b/LightweightIocContainer/Interfaces/Registrations/IDefaultRegistration.cs
@@ -1,39 +1,20 @@
-// Author: simon.gockner
-// Created: 2019-05-20
+// Author: Gockner, Simon
+// Created: 2019-11-22
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
-using LightweightIocContainer.Interfaces.Installers;
namespace LightweightIocContainer.Interfaces.Registrations
{
///
- /// The default registration that is used to register a for the Interface it implements
+ /// The to register a for the Interface it implements
///
- /// The registered Interface
- public interface IDefaultRegistration : IRegistrationBase
+ /// The of the interface
+ public interface IDefaultRegistration : IRegistrationBase
{
///
- /// The that implements the that is registered with this
+ /// The that implements the that is registered with this
///
Type ImplementationType { get; }
-
- ///
- /// The Lifestyle of Instances that are created with this
- ///
- Lifestyle Lifestyle { get; }
-
- ///
- /// This is invoked when an instance of this type is created.
- /// Can be set in the by calling
- ///
- Action OnCreateAction { get; }
-
- ///
- /// Pass an that will be invoked when an instance of this type is created
- ///
- /// The
- /// The current instance of this
- IDefaultRegistration OnCreate(Action action);
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs
new file mode 100644
index 0000000..65d6dd6
--- /dev/null
+++ b/LightweightIocContainer/Interfaces/Registrations/IRegistration.cs
@@ -0,0 +1,24 @@
+// Author: simon.gockner
+// Created: 2019-05-20
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+
+namespace LightweightIocContainer.Interfaces.Registrations
+{
+ ///
+ /// The base registration that is used to register an Interface
+ ///
+ public interface IRegistration
+ {
+ ///
+ /// The name of the
+ ///
+ string Name { get; }
+
+ ///
+ /// The of the Interface that is registered with this
+ ///
+ Type InterfaceType { get; }
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs
index cc39e41..7f7e3dd 100644
--- a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs
+++ b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs
@@ -3,22 +3,58 @@
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
+using LightweightIocContainer.Exceptions;
+using LightweightIocContainer.Interfaces.Installers;
namespace LightweightIocContainer.Interfaces.Registrations
{
///
- /// The base registration that is used to register an Interface
+ /// The that is used to register an Interface
///
- public interface IRegistrationBase
+ /// The registered Interface
+ public interface IRegistrationBase : IRegistration
{
///
- /// The name of the
+ /// The Lifestyle of Instances that are created with this
///
- string Name { get; }
+ Lifestyle Lifestyle { get; }
///
- /// The of the Interface that is registered with this
+ /// This is invoked when an instance of this type is created.
+ /// Can be set in the by calling
///
- Type InterfaceType { get; }
+ Action OnCreateAction { get; }
+
+ ///
+ /// Pass an that will be invoked when an instance of this type is created
+ ///
+ /// The
+ /// The current instance of this
+ IRegistrationBase OnCreate(Action action);
+
+ ///
+ /// An of parameters that are used to an instance of this
+ /// Can be set in the by calling
+ ///
+ object[] Parameters { get; }
+
+ ///
+ /// Pass parameters that will be used to an instance of this
+ /// Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving
+ ///
+ /// The parameters
+ /// The current instance of this
+ /// are already set or no parameters given
+ IRegistrationBase WithParameters(params object[] parameters);
+
+ ///
+ /// Pass parameters that will be used to an instance of this
+ /// Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving
+ ///
+ /// The parameters with their position
+ /// The current instance of this
+ /// are already set or no parameters given
+ IRegistrationBase WithParameters(params (int index, object parameter)[] parameters);
+
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs
new file mode 100644
index 0000000..ad9f188
--- /dev/null
+++ b/LightweightIocContainer/Interfaces/Registrations/ISingleTypeRegistration.cs
@@ -0,0 +1,27 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+
+namespace LightweightIocContainer.Interfaces.Registrations
+{
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the
+ public interface ISingleTypeRegistration : IRegistrationBase
+ {
+ ///
+ /// that is invoked instead of creating an instance of this the default way
+ ///
+ Func FactoryMethod { get; }
+
+ ///
+ /// Pass a that will be invoked instead of creating an instance of this the default way
+ ///
+ /// The
+ /// The current instance of this
+ ISingleTypeRegistration WithFactoryMethod(Func factoryMethod);
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Interfaces/Registrations/ITypedFactoryRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/ITypedFactoryRegistration.cs
index 584a290..12c361e 100644
--- a/LightweightIocContainer/Interfaces/Registrations/ITypedFactoryRegistration.cs
+++ b/LightweightIocContainer/Interfaces/Registrations/ITypedFactoryRegistration.cs
@@ -10,7 +10,7 @@ namespace LightweightIocContainer.Interfaces.Registrations
/// The registration that is used to register an abstract typed factory
///
/// The type of the abstract typed factory
- public interface ITypedFactoryRegistration : IRegistrationBase
+ public interface ITypedFactoryRegistration : IRegistration
{
///
/// The class that contains the implemented abstract factory of this
diff --git a/LightweightIocContainer/Interfaces/Registrations/IUnitTestCallbackRegistration.cs b/LightweightIocContainer/Interfaces/Registrations/IUnitTestCallbackRegistration.cs
index e5831d8..d10f74e 100644
--- a/LightweightIocContainer/Interfaces/Registrations/IUnitTestCallbackRegistration.cs
+++ b/LightweightIocContainer/Interfaces/Registrations/IUnitTestCallbackRegistration.cs
@@ -2,17 +2,21 @@
// Created: 2019-10-15
// Copyright(c) 2019 SimonG. All Rights Reserved.
+using System;
+
namespace LightweightIocContainer.Interfaces.Registrations
{
///
- /// A special that allows to set a as a callback that is called on
+ /// A special that allows to set a as a callback that is called on
///
///
- public interface IUnitTestCallbackRegistration : IRegistrationBase
+ [Obsolete("IUnitTestCallbackRegistration is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
+ public interface IUnitTestCallbackRegistration : IRegistration
{
///
/// An that is set as a callback that is called on
///
+ [Obsolete("UnitTestResolveCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
ResolveCallback UnitTestResolveCallback { get; }
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/InternalResolvePlaceholder.cs b/LightweightIocContainer/InternalResolvePlaceholder.cs
new file mode 100644
index 0000000..8f97059
--- /dev/null
+++ b/LightweightIocContainer/InternalResolvePlaceholder.cs
@@ -0,0 +1,14 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+namespace LightweightIocContainer
+{
+ ///
+ /// An internal placeholder that is used during the resolving process
+ ///
+ internal class InternalResolvePlaceholder
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/IocContainer.cs b/LightweightIocContainer/IocContainer.cs
index 0112cfd..dd6b580 100644
--- a/LightweightIocContainer/IocContainer.cs
+++ b/LightweightIocContainer/IocContainer.cs
@@ -17,19 +17,19 @@ using LightweightIocContainer.Registrations;
namespace LightweightIocContainer
{
///
- /// The main container that carries all the s and can resolve all the types you'll ever want
+ /// The main container that carries all the s and can resolve all the types you'll ever want
///
public class IocContainer : IIocContainer
{
private readonly RegistrationFactory _registrationFactory;
- private readonly List _registrations = new List();
+ private readonly List _registrations = new List();
private readonly List<(Type type, object instance)> _singletons = new List<(Type, object)>();
private readonly List<(Type type, Type scope, ConditionalWeakTable
/// The Interface to register
/// The Type that implements the interface
- /// The for this
- /// The created
+ /// The for this
+ /// The created
public IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient) where TImplementation : TInterface
{
IDefaultRegistration registration = _registrationFactory.Register(lifestyle);
@@ -71,11 +71,11 @@ namespace LightweightIocContainer
/// Register a without an interface
///
/// The to register
- /// The for this
- /// The created
- public IDefaultRegistration Register(Lifestyle lifestyle = Lifestyle.Transient)
+ /// The for this
+ /// The created
+ public ISingleTypeRegistration Register(Lifestyle lifestyle = Lifestyle.Transient)
{
- IDefaultRegistration registration = _registrationFactory.Register(lifestyle);
+ ISingleTypeRegistration registration = _registrationFactory.Register(lifestyle);
Register(registration);
return registration;
@@ -87,7 +87,7 @@ namespace LightweightIocContainer
/// The Interface to register
/// The Type that implements the interface
/// The Type of the multiton scope
- /// The created
+ /// The created
public IMultitonRegistration Register() where TImplementation : TInterface
{
IMultitonRegistration registration = _registrationFactory.Register();
@@ -100,7 +100,7 @@ namespace LightweightIocContainer
/// Register an Interface as an abstract typed factory
///
/// The abstract typed factory to register
- /// The created
+ /// The created
public ITypedFactoryRegistration RegisterFactory()
{
ITypedFactoryRegistration registration = _registrationFactory.RegisterFactory();
@@ -114,7 +114,8 @@ namespace LightweightIocContainer
///
/// The Interface to register
/// The for the callback
- /// The created
+ /// The created
+ [Obsolete("RegisterUnitTestCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public IUnitTestCallbackRegistration RegisterUnitTestCallback(ResolveCallback unitTestCallback)
{
IUnitTestCallbackRegistration registration = _registrationFactory.RegisterUnitTestCallback(unitTestCallback);
@@ -124,11 +125,11 @@ namespace LightweightIocContainer
}
///
- /// Add the to the the
+ /// Add the to the the
///
- /// The given
+ /// The given
/// The is already registered in this
- private void Register(IRegistrationBase registration)
+ private void Register(IRegistration registration)
{
//if type is already registered
if (_registrations.Any(r => r.InterfaceType == registration.InterfaceType))
@@ -195,7 +196,7 @@ namespace LightweightIocContainer
/// The registration for the given has an unknown
private T ResolveInternal(object[] arguments, List resolveStack = null)
{
- IRegistrationBase registration = _registrations.FirstOrDefault(r => r.InterfaceType == typeof(T));
+ IRegistration registration = _registrations.FirstOrDefault(r => r.InterfaceType == typeof(T));
if (registration == null)
throw new TypeNotRegisteredException(typeof(T));
@@ -209,11 +210,14 @@ namespace LightweightIocContainer
T resolvedInstance;
+ //TODO: remove this #pragma when IUnitTestCallbackRegistration is removed
+#pragma warning disable 618
if (registration is IUnitTestCallbackRegistration unitTestCallbackRegistration)
{
resolvedInstance = unitTestCallbackRegistration.UnitTestResolveCallback.Invoke(arguments);
}
- else if (registration is IDefaultRegistration defaultRegistration)
+#pragma warning restore 618
+ else if (registration is IRegistrationBase defaultRegistration)
{
if (defaultRegistration.Lifestyle == Lifestyle.Singleton)
resolvedInstance = GetOrCreateSingletonInstance(defaultRegistration, arguments, resolveStack);
@@ -242,7 +246,7 @@ namespace LightweightIocContainer
/// The arguments to resolve
/// The current resolve stack
/// An existing or newly created singleton instance of the given
- private T GetOrCreateSingletonInstance(IDefaultRegistration registration, object[] arguments, List resolveStack)
+ private T GetOrCreateSingletonInstance(IRegistrationBase registration, object[] arguments, List resolveStack)
{
//if a singleton instance exists return it
object instance = _singletons.FirstOrDefault(s => s.type == typeof(T)).instance;
@@ -306,15 +310,82 @@ namespace LightweightIocContainer
/// The constructor arguments
/// The current resolve stack
/// A newly created instance of the given
- private T CreateInstance(IDefaultRegistration registration, object[] arguments, List resolveStack)
+ private T CreateInstance(IRegistrationBase registration, object[] arguments, List resolveStack)
{
- arguments = ResolveConstructorArguments(registration.ImplementationType, arguments, resolveStack);
- T instance = (T) Activator.CreateInstance(registration.ImplementationType, arguments);
+ if (registration.Parameters != null)
+ arguments = UpdateArgumentsWithRegistrationParameters(registration, arguments);
+
+ T instance;
+ if (registration is IDefaultRegistration defaultRegistration)
+ {
+ arguments = ResolveConstructorArguments(defaultRegistration.ImplementationType, arguments, resolveStack);
+ instance = (T) Activator.CreateInstance(defaultRegistration.ImplementationType, arguments);
+ }
+ else if (registration is ISingleTypeRegistration singleTypeRegistration)
+ {
+ if (singleTypeRegistration.InterfaceType.IsInterface && singleTypeRegistration.FactoryMethod == null)
+ throw new InvalidRegistrationException($"Can't register an interface without its implementation type or without a factory method (Type: {singleTypeRegistration.InterfaceType}).");
+
+ if (singleTypeRegistration.FactoryMethod == null) //type registration without interface -> just create this type
+ {
+ arguments = ResolveConstructorArguments(singleTypeRegistration.InterfaceType, arguments, resolveStack);
+ instance = (T)Activator.CreateInstance(singleTypeRegistration.InterfaceType, arguments);
+ }
+ else //factory method set to create the instance
+ instance = singleTypeRegistration.FactoryMethod(this);
+ }
+ else
+ throw new UnknownRegistrationException($"There is no registration of type {registration.GetType().Name}.");
+
registration.OnCreateAction?.Invoke(instance); //TODO: Allow async OnCreateAction?
return instance;
}
+ ///
+ /// Update the given arguments with the of the given
+ ///
+ /// The given
+ /// The of the given
+ /// The constructor arguments
+ /// The argument list updated with the
+ private object[] UpdateArgumentsWithRegistrationParameters(IRegistrationBase registration, object[] arguments)
+ {
+ if (arguments != null && arguments.Any()) //if more arguments were passed to resolve
+ {
+ int argumentsSize = registration.Parameters.Length + arguments.Length;
+ object[] newArguments = new object[argumentsSize];
+
+ for (int i = 0; i < argumentsSize; i++)
+ {
+ if (i < registration.Parameters.Length) //if `i` is bigger than the length of the parameters, take the given arguments
+ {
+ object currentParameter = registration.Parameters[i];
+ if (!(currentParameter is InternalResolvePlaceholder)) //use the parameter at the current index if it is not a placeholder
+ {
+ newArguments[i] = currentParameter;
+ continue;
+ }
+ }
+
+ object firstArgument = arguments.FirstOrGiven(a => !(a is InternalResolvePlaceholder)); //find the first argument that is not a placeholder
+ if (firstArgument is InternalResolvePlaceholder) //no more arguments available
+ break; //there won't be any more arguments
+
+ newArguments[i] = firstArgument;
+
+ int indexOfFirstArgument = Array.IndexOf(arguments, firstArgument);
+ arguments[indexOfFirstArgument] = new InternalResolvePlaceholder();
+ }
+
+ arguments = newArguments;
+ }
+ else //no more arguments were passed to resolve -> only use parameters set during registration
+ arguments = registration.Parameters;
+
+ return arguments;
+ }
+
///
/// Resolve the missing constructor arguments
///
@@ -432,13 +503,5 @@ namespace LightweightIocContainer
_singletons.Clear();
_multitons.Clear();
}
-
- ///
- /// An internal placeholder that is used during the resolving process
- ///
- private class InternalResolvePlaceholder
- {
-
- }
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/Lifestyle.cs b/LightweightIocContainer/Lifestyle.cs
index d3dc7fc..a7141d3 100644
--- a/LightweightIocContainer/Lifestyle.cs
+++ b/LightweightIocContainer/Lifestyle.cs
@@ -7,7 +7,7 @@ using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer
{
///
- /// The Lifestyles that can be used for a
+ /// The Lifestyles that can be used for a
///
public enum Lifestyle
{
diff --git a/LightweightIocContainer/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml
index e0c48cb..067c4f7 100644
--- a/LightweightIocContainer/LightweightIocContainer.xml
+++ b/LightweightIocContainer/LightweightIocContainer.xml
@@ -222,12 +222,12 @@
- An unknown was used
+ An unknown was used
- An unknown was used
+ An unknown was used
The exception message
@@ -295,7 +295,7 @@
- The main container that carries all the s and can resolve all the types you'll ever want
+ The main container that carries all the s and can resolve all the types you'll ever want
@@ -311,16 +311,16 @@
The Interface to registerThe Type that implements the interface
- The for this
- The created
+ The for this
+ The created
Register a without an interface
The to register
- The for this
- The created
+ The for this
+ The created
@@ -329,14 +329,14 @@
The Interface to registerThe Type that implements the interfaceThe Type of the multiton scope
- The created
+ The created
Register an Interface as an abstract typed factory
The abstract typed factory to register
- The created
+ The created
@@ -344,7 +344,7 @@
The Interface to register
The for the callback
- The created
+ The created
@@ -391,65 +391,113 @@
- Install the needed s in the given
+ Install the needed s in the given
The current
- The default registration that is used to register a for the Interface it implements
+ The to register a for the Interface it implements
- The registered Interface
+ The of the interface
- The that implements the that is registered with this
+ The that implements the that is registered with this
+
+
+
+
+ The registration that is used to register a multiton
+
+ The registered interface
+
+
+
+ The of the multiton scope
+
+
+
+
+ The base registration that is used to register an Interface
+
+
+
+
+ The name of the
+
+
+
+
+ The of the Interface that is registered with this
+
+
+
+
+ The that is used to register an Interface
+ The registered Interface
-
+
- The Lifestyle of Instances that are created with this
+ The Lifestyle of Instances that are created with this
-
+
This is invoked when an instance of this type is created.
- Can be set in the by calling
+ Can be set in the by calling
-
+
Pass an that will be invoked when an instance of this type is created
The
- The current instance of this
+ The current instance of this
-
+
- The registration that is used to register a multiton
+ An of parameters that are used to an instance of this
+ Can be set in the by calling
- The registered interface
-
+
- The of the multiton scope
+ Pass parameters that will be used to an instance of this
+ Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving
+ The parameters
+ The current instance of this
+ are already set or no parameters given
-
+
- The base registration that is used to register an Interface
+ Pass parameters that will be used to an instance of this
+ Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving
+ The parameters with their position
+ The current instance of this
+ are already set or no parameters given
-
+
- The name of the
+ The to register either only an interface or only a
+ The of the
-
+
- The of the Interface that is registered with this
+ that is invoked instead of creating an instance of this the default way
+
+
+ Pass a that will be invoked instead of creating an instance of this the default way
+
+ The
+ The current instance of this
+
The registration that is used to register an abstract typed factory
@@ -463,7 +511,7 @@
- A special that allows to set a as a callback that is called on
+ A special that allows to set a as a callback that is called on
@@ -472,14 +520,19 @@
An that is set as a callback that is called on
+
+
+ An internal placeholder that is used during the resolving process
+
+
- The main container that carries all the s and can resolve all the types you'll ever want
+ The main container that carries all the s and can resolve all the types you'll ever want
- The main container that carries all the s and can resolve all the types you'll ever want
+ The main container that carries all the s and can resolve all the types you'll ever want
@@ -495,16 +548,16 @@
The Interface to registerThe Type that implements the interface
- The for this
- The created
+ The for this
+ The created
Register a without an interface
The to register
- The for this
- The created
+ The for this
+ The created
@@ -513,14 +566,14 @@
The Interface to registerThe Type that implements the interfaceThe Type of the multiton scope
- The created
+ The created
Register an Interface as an abstract typed factory
The abstract typed factory to register
- The created
+ The created
@@ -528,13 +581,13 @@
The Interface to register
The for the callback
- The created
+ The created
-
+
- Add the to the the
+ Add the to the the
- The given
+ The given The is already registered in this
@@ -573,7 +626,7 @@
The given is not registered in this The registration for the given has an unknown
-
+
Gets or creates a singleton instance of a given
@@ -595,7 +648,7 @@
No arguments givenScope argument not given
-
+
Creates an instance of a given
@@ -605,6 +658,15 @@
The current resolve stack
A newly created instance of the given
+
+
+ Update the given arguments with the of the given
+
+ The given
+ The of the given
+ The constructor arguments
+ The argument list updated with the
+
Resolve the missing constructor arguments
@@ -633,14 +695,9 @@
The method
-
-
- An internal placeholder that is used during the resolving process
-
-
- The Lifestyles that can be used for a
+ The Lifestyles that can be used for a
@@ -660,73 +717,110 @@
- The default registration that is used to register a for the Interface it implements
+ The to register a for the Interface it implements
- The registered Interface
+ The of the interface
- The default registration that is used to register a for the Interface it implements
+ The to register a for the Interface it implements
+
+ The of the interface
+ The of the implementation
+ The of the
+
+
+
+ The that implements the that is registered with this
+
+
+
+
+ The registration that is used to register a multiton
+
+ The registered interface
+
+
+
+ The registration that is used to register a multiton
The of the Interface
The of the Implementation
- The of the registration
+ The of the Multiton Scope
-
+
- The name of the
+ The of the multiton scope
-
+
- The of the Interface that is registered with this
+ The that is used to register an Interface
+ The registered Interface
-
+
+
+ The that is used to register an Interface
+
+ The of the Interface
+ The of the registration
+
+
+
+ The name of the
+
+
+
- The that implements the that is registered with this
+ The of the Interface that is registered with this
-
+
- The of Instances that are created with this
+ The of Instances that are created with this
-
+
This is invoked when an instance of this type is created.
- Can be set in the by calling
+ Can be set in the by calling
-
+
Pass an that will be invoked when an instance of this is created
The
- The current instance of this
+ The current instance of this
-
+
- The registration that is used to register a multiton
+ An of parameters that are used to an instance of this
+ Can be set in the by calling
- The registered interface
-
+
- The registration that is used to register a multiton
+ Pass parameters that will be used to an instance of this
+ Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving
- The of the Interface
- The of the Implementation
- The of the Multiton Scope
+ The parameters
+ The current instance of this
+ are already set or no parameters given
-
+
- The of the multiton scope
+ Pass parameters that will be used to an instance of this
+ Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving
+ The parameters with their position
+ The current instance of this
+ are already set or no parameters given
- A factory to register interfaces and factories in an and create the needed s
+ A factory to register interfaces and factories in an and create the needed s
@@ -740,11 +834,11 @@
- Register a without an interface and create a
+ Register a without an interface and create a
- The to register
- The for this
- A new created with the given parameters
+ The to register
+ The for this
+ A new created with the given parameters
@@ -762,6 +856,31 @@
The abstract typed factory to registerA new created with the given parameters
+
+
+ The to register either only an interface or only a
+
+ The of the
+
+
+
+ The to register either only an interface or only a
+
+ The of the interface or
+ The of the
+
+
+
+ that is invoked instead of creating an instance of this the default way
+
+
+
+
+ Pass a that will be invoked instead of creating an instance of this the default way
+
+ The
+ The current instance of this
+
The registration that is used to register an abstract typed factory
@@ -799,13 +918,13 @@
- A special that allows to set a as a callback that is called on
+ A special that allows to set a as a callback that is called on
- A special that allows to set a as a callback that is called on
+ A special that allows to set a as a callback that is called on
The of the interface
The that is set as a callback
diff --git a/LightweightIocContainer/Registrations/DefaultRegistration.cs b/LightweightIocContainer/Registrations/DefaultRegistration.cs
index 9aa0b34..f8c5c47 100644
--- a/LightweightIocContainer/Registrations/DefaultRegistration.cs
+++ b/LightweightIocContainer/Registrations/DefaultRegistration.cs
@@ -1,71 +1,34 @@
-// Author: simon.gockner
-// Created: 2019-05-20
+// Author: Gockner, Simon
+// Created: 2019-11-22
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
-using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
{
///
- /// The default registration that is used to register a for the Interface it implements
+ /// The to register a for the Interface it implements
///
- /// The registered Interface
- public class DefaultRegistration : IDefaultRegistration
+ /// The of the interface
+ public class DefaultRegistration : RegistrationBase, IDefaultRegistration
{
///
- /// The default registration that is used to register a for the Interface it implements
+ /// The to register a for the Interface it implements
///
- /// The of the Interface
- /// The of the Implementation
- /// The of the registration
+ /// The of the interface
+ /// The of the implementation
+ /// The of the
public DefaultRegistration(Type interfaceType, Type implementationType, Lifestyle lifestyle)
+ : base(interfaceType, lifestyle)
{
- InterfaceType = interfaceType;
ImplementationType = implementationType;
- Lifestyle = lifestyle;
-
Name = $"{InterfaceType.Name}, {ImplementationType.Name}, Lifestyle: {Lifestyle.ToString()}";
}
///
- /// The name of the
- ///
- public string Name { get; }
-
- ///
- /// The of the Interface that is registered with this
- ///
- public Type InterfaceType { get; }
-
- ///
- /// The that implements the that is registered with this
+ /// The that implements the that is registered with this
///
public Type ImplementationType { get; }
-
- ///
- /// The of Instances that are created with this
- ///
- public Lifestyle Lifestyle { get; }
-
-
- ///
- /// This is invoked when an instance of this type is created.
- /// Can be set in the by calling
- ///
- public Action OnCreateAction { get; private set; }
-
-
- ///
- /// Pass an that will be invoked when an instance of this is created
- ///
- /// The
- /// The current instance of this
- public IDefaultRegistration OnCreate(Action action)
- {
- OnCreateAction = action;
- return this;
- }
}
}
\ No newline at end of file
diff --git a/LightweightIocContainer/Registrations/RegistrationBase.cs b/LightweightIocContainer/Registrations/RegistrationBase.cs
new file mode 100644
index 0000000..512fed9
--- /dev/null
+++ b/LightweightIocContainer/Registrations/RegistrationBase.cs
@@ -0,0 +1,119 @@
+// Author: simon.gockner
+// Created: 2019-05-20
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using System.Linq;
+using LightweightIocContainer.Exceptions;
+using LightweightIocContainer.Interfaces;
+using LightweightIocContainer.Interfaces.Installers;
+using LightweightIocContainer.Interfaces.Registrations;
+
+namespace LightweightIocContainer.Registrations
+{
+ ///
+ /// The that is used to register an Interface
+ ///
+ /// The registered Interface
+ public abstract class RegistrationBase : IRegistrationBase
+ {
+ ///
+ /// The that is used to register an Interface
+ ///
+ /// The of the Interface
+ /// The of the registration
+ protected RegistrationBase(Type interfaceType, Lifestyle lifestyle)
+ {
+ InterfaceType = interfaceType;
+ Lifestyle = lifestyle;
+ }
+
+ ///
+ /// The name of the
+ ///
+ public string Name { get; protected set; }
+
+ ///
+ /// The of the Interface that is registered with this
+ ///
+ public Type InterfaceType { get; }
+
+ ///
+ /// The of Instances that are created with this
+ ///
+ public Lifestyle Lifestyle { get; }
+
+
+ ///
+ /// This is invoked when an instance of this type is created.
+ /// Can be set in the by calling
+ ///
+ public Action OnCreateAction { get; private set; }
+
+
+ ///
+ /// Pass an that will be invoked when an instance of this is created
+ ///
+ /// The
+ /// The current instance of this
+ public IRegistrationBase OnCreate(Action action)
+ {
+ OnCreateAction = action;
+ return this;
+ }
+
+ ///
+ /// An of parameters that are used to an instance of this
+ /// Can be set in the by calling
+ ///
+ public object[] Parameters { get; private set; }
+
+ ///
+ /// Pass parameters that will be used to an instance of this
+ /// Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving
+ ///
+ /// The parameters
+ /// The current instance of this
+ /// are already set or no parameters given
+ public IRegistrationBase WithParameters(params object[] parameters)
+ {
+ if (Parameters != null)
+ throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
+
+ if (parameters == null || !parameters.Any())
+ throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
+
+ Parameters = parameters;
+ return this;
+ }
+
+ ///
+ /// Pass parameters that will be used to an instance of this
+ /// Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving
+ ///
+ /// The parameters with their position
+ /// The current instance of this
+ /// are already set or no parameters given
+ public IRegistrationBase WithParameters(params (int index, object parameter)[] parameters)
+ {
+ if (Parameters != null)
+ throw new InvalidRegistrationException($"Don't use `WithParameters()` method twice (Type: {InterfaceType}).");
+
+ if (parameters == null || !parameters.Any())
+ throw new InvalidRegistrationException($"No parameters given to `WithParameters()` method (Type: {InterfaceType}).");
+
+ var lastIndex = parameters.Max(p => p.index);
+ Parameters = new object[lastIndex + 1];
+
+ for (int i = 0; i < Parameters.Length; i++)
+ {
+ if (parameters.Any(p => p.index == i))
+ Parameters[i] = parameters.First(p => p.index == i).parameter;
+ else
+ Parameters[i] = new InternalResolvePlaceholder();
+ }
+
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Registrations/RegistrationFactory.cs b/LightweightIocContainer/Registrations/RegistrationFactory.cs
index 1482424..d780413 100644
--- a/LightweightIocContainer/Registrations/RegistrationFactory.cs
+++ b/LightweightIocContainer/Registrations/RegistrationFactory.cs
@@ -3,7 +3,6 @@
// Copyright(c) 2019 SimonG. All Rights Reserved.
using System;
-using LightweightIocContainer.Exceptions;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Installers;
using LightweightIocContainer.Interfaces.Registrations;
@@ -11,7 +10,7 @@ using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
{
///
- /// A factory to register interfaces and factories in an and create the needed s
+ /// A factory to register interfaces and factories in an and create the needed s
///
internal class RegistrationFactory
{
@@ -35,17 +34,14 @@ namespace LightweightIocContainer.Registrations
}
///
- /// Register a without an interface and create a
+ /// Register a without an interface and create a
///
- /// The to register
- /// The for this
- /// A new created with the given parameters
- public IDefaultRegistration Register(Lifestyle lifestyle)
+ /// The to register
+ /// The for this
+ /// A new created with the given parameters
+ public ISingleTypeRegistration Register(Lifestyle lifestyle)
{
- if (typeof(TImplementation).IsInterface)
- throw new InvalidRegistrationException("Can't register an interface without its implementation type.");
-
- return Register(lifestyle);
+ return new SingleTypeRegistration(typeof(T), lifestyle);
}
///
@@ -70,6 +66,7 @@ namespace LightweightIocContainer.Registrations
return new TypedFactoryRegistration(typeof(TFactory), _iocContainer);
}
+ [Obsolete("RegisterUnitTestCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public IUnitTestCallbackRegistration RegisterUnitTestCallback(ResolveCallback unitTestResolveCallback)
{
return new UnitTestCallbackRegistration(typeof(TInterface), unitTestResolveCallback);
diff --git a/LightweightIocContainer/Registrations/SingleTypeRegistration.cs b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs
new file mode 100644
index 0000000..7a961c3
--- /dev/null
+++ b/LightweightIocContainer/Registrations/SingleTypeRegistration.cs
@@ -0,0 +1,44 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using LightweightIocContainer.Interfaces;
+using LightweightIocContainer.Interfaces.Registrations;
+
+namespace LightweightIocContainer.Registrations
+{
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the
+ public class SingleTypeRegistration : RegistrationBase, ISingleTypeRegistration
+ {
+ ///
+ /// The to register either only an interface or only a
+ ///
+ /// The of the interface or
+ /// The of the
+ public SingleTypeRegistration(Type interfaceType, Lifestyle lifestyle)
+ : base(interfaceType, lifestyle)
+ {
+ Name = $"{InterfaceType.Name}, Lifestyle: {Lifestyle.ToString()}";
+ }
+
+ ///
+ /// that is invoked instead of creating an instance of this the default way
+ ///
+ public Func FactoryMethod { get; private set; }
+
+ ///
+ /// Pass a that will be invoked instead of creating an instance of this the default way
+ ///
+ /// The
+ /// The current instance of this
+ public ISingleTypeRegistration WithFactoryMethod(Func factoryMethod)
+ {
+ FactoryMethod = factoryMethod;
+ return this;
+ }
+ }
+}
\ No newline at end of file
diff --git a/LightweightIocContainer/Registrations/UnitTestCallbackRegistration.cs b/LightweightIocContainer/Registrations/UnitTestCallbackRegistration.cs
index 8f6e171..c489510 100644
--- a/LightweightIocContainer/Registrations/UnitTestCallbackRegistration.cs
+++ b/LightweightIocContainer/Registrations/UnitTestCallbackRegistration.cs
@@ -9,13 +9,14 @@ using LightweightIocContainer.Interfaces.Registrations;
namespace LightweightIocContainer.Registrations
{
///
- /// A special that allows to set a as a callback that is called on
+ /// A special that allows to set a as a callback that is called on
///
///
+ [Obsolete("UnitTestCallbackRegistration is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public class UnitTestCallbackRegistration : IUnitTestCallbackRegistration
{
///
- /// A special that allows to set a as a callback that is called on
+ /// A special that allows to set a as a callback that is called on
///
/// The of the interface
/// The that is set as a callback
diff --git a/Test.LightweightIocContainer/AssemblyInstallerTest.cs b/Test.LightweightIocContainer/AssemblyInstallerTest.cs
index 30874e0..c605328 100644
--- a/Test.LightweightIocContainer/AssemblyInstallerTest.cs
+++ b/Test.LightweightIocContainer/AssemblyInstallerTest.cs
@@ -25,7 +25,7 @@ namespace Test.LightweightIocContainer
{
public void Install(IIocContainer container)
{
- container.Register>();
+ container.Register>();
}
}
@@ -54,7 +54,7 @@ namespace Test.LightweightIocContainer
AssemblyInstaller assemblyInstaller = new AssemblyInstaller(assemblyMock.Object);
assemblyInstaller.Install(iocContainerMock.Object);
- iocContainerMock.Verify(ioc => ioc.Register>>(It.IsAny()), Times.Once);
+ iocContainerMock.Verify(ioc => ioc.Register>>(It.IsAny()), Times.Once);
}
[Test]
diff --git a/Test.LightweightIocContainer/DefaultRegistrationTest.cs b/Test.LightweightIocContainer/DefaultRegistrationTest.cs
deleted file mode 100644
index 70cb966..0000000
--- a/Test.LightweightIocContainer/DefaultRegistrationTest.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Author: Gockner, Simon
-// Created: 2019-06-06
-// Copyright(c) 2019 SimonG. All Rights Reserved.
-
-using System;
-using LightweightIocContainer;
-using LightweightIocContainer.Interfaces;
-using LightweightIocContainer.Interfaces.Registrations;
-using LightweightIocContainer.Registrations;
-using Moq;
-using NUnit.Framework;
-
-namespace Test.LightweightIocContainer
-{
- [TestFixture]
- public class DefaultRegistrationTest
- {
- #region TestClasses
-
- private interface ITest
- {
- void DoSomething();
- }
-
- private class Test : ITest
- {
- public void DoSomething()
- {
- throw new Exception();
- }
- }
-
- #endregion
-
-
- [Test]
- public void TestOnCreate()
- {
- RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
- IDefaultRegistration testRegistration = registrationFactory.Register(Lifestyle.Transient).OnCreate(t => t.DoSomething());
-
- ITest test = new Test();
-
- Assert.Throws(() => testRegistration.OnCreateAction(test));
- }
- }
-}
\ No newline at end of file
diff --git a/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs b/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs
new file mode 100644
index 0000000..be23d2e
--- /dev/null
+++ b/Test.LightweightIocContainer/IocContainerParameterRegistrationTest.cs
@@ -0,0 +1,169 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using JetBrains.Annotations;
+using LightweightIocContainer;
+using LightweightIocContainer.Interfaces;
+using NUnit.Framework;
+
+namespace Test.LightweightIocContainer
+{
+ [TestFixture]
+ // ReSharper disable MemberHidesStaticFromOuterClass
+ public class IocContainerParameterRegistrationTest
+ {
+ #region TestClasses
+
+ [UsedImplicitly]
+ public interface IA
+ {
+ IB B { get; }
+ IC C { get; }
+ }
+
+ [UsedImplicitly]
+ public interface IB
+ {
+
+ }
+
+ [UsedImplicitly]
+ public interface IC
+ {
+
+ }
+
+ [UsedImplicitly]
+ public interface ID
+ {
+ IA A { get; }
+ IA A2 { get; }
+ IB B { get; }
+ IC C { get; }
+ }
+
+ [UsedImplicitly]
+ private class A : IA
+ {
+ public A(IB b, IC c)
+ {
+ B = b;
+ C = c;
+ }
+
+ public IB B { get; }
+ public IC C { get; }
+ }
+
+ [UsedImplicitly]
+ private class B : IB
+ {
+ public B(IC c)
+ {
+ }
+ }
+
+ [UsedImplicitly]
+ private class C : IC
+ {
+
+ }
+
+ [UsedImplicitly]
+ private class D : ID
+ {
+ public D(IA a, IA a2, IB b, IC c)
+ {
+ A = a;
+ A2 = a2;
+ B = b;
+ C = c;
+ }
+
+ public IA A { get; }
+ public IA A2 { get; }
+ public IB B { get; }
+ public IC C { get; }
+ }
+
+ #endregion TestClasses
+
+ private IIocContainer _iocContainer;
+
+ [SetUp]
+ public void SetUp()
+ {
+ _iocContainer = new IocContainer();
+ }
+
+
+ [TearDown]
+ public void TearDown()
+ {
+ _iocContainer.Dispose();
+ }
+
+
+ [Test]
+ public void TestResolveOnlyRegistrationParameters()
+ {
+ IC c = new C();
+ IB b = new B(c);
+
+ _iocContainer.Register().WithParameters(b, c);
+ IA a = _iocContainer.Resolve();
+
+ Assert.AreEqual(b, a.B);
+ Assert.AreEqual(c, a.C);
+ }
+
+ [Test]
+ public void TestResolveRegistrationAndResolveParameters()
+ {
+ IC c = new C();
+ IB b = new B(c);
+
+ _iocContainer.Register().WithParameters(b);
+ IA a = _iocContainer.Resolve(c);
+
+ Assert.AreEqual(b, a.B);
+ Assert.AreEqual(c, a.C);
+ }
+
+ [Test]
+ public void TestResolveRegistrationAndResolveParametersMixedOrder()
+ {
+ IC c = new C();
+ IB b = new B(c);
+ IA a = new A(b, c);
+ IA a2 = new A(b, c);
+
+ _iocContainer.Register().WithParameters((0, a), (2, b), (3, c));
+ ID d = _iocContainer.Resolve(a2);
+
+ Assert.AreEqual(a, d.A);
+ Assert.AreEqual(a2, d.A2);
+ Assert.AreEqual(b, d.B);
+ Assert.AreEqual(c, d.C);
+ }
+
+ [Test]
+ public void TestResolveRegistrationParametersAndResolvedParameters()
+ {
+ IC c = new C();
+ IB b = new B(c);
+ IA a = new A(b, c);
+ IA a2 = new A(b, c);
+
+ _iocContainer.Register().WithParameters(a2);
+ _iocContainer.Register();
+ _iocContainer.Register();
+
+ ID d = _iocContainer.Resolve(a);
+
+ Assert.AreEqual(a, d.A2);
+ Assert.AreEqual(a2, d.A);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test.LightweightIocContainer/IocContainerTest.cs b/Test.LightweightIocContainer/IocContainerTest.cs
index 1658ab8..717255b 100644
--- a/Test.LightweightIocContainer/IocContainerTest.cs
+++ b/Test.LightweightIocContainer/IocContainerTest.cs
@@ -1,3 +1,4 @@
+using System;
using JetBrains.Annotations;
using LightweightIocContainer;
using LightweightIocContainer.Exceptions;
@@ -43,6 +44,11 @@ namespace Test.LightweightIocContainer
void ClearMultitonInstance();
}
+ private interface IFoo
+ {
+
+ }
+
private class Test : ITest
{
@@ -60,6 +66,11 @@ namespace Test.LightweightIocContainer
{
}
+
+ public TestConstructor(IFoo foo, string name)
+ {
+
+ }
}
[UsedImplicitly]
@@ -83,6 +94,12 @@ namespace Test.LightweightIocContainer
}
}
+ [UsedImplicitly]
+ private class Foo : IFoo
+ {
+
+ }
+
public class MultitonScope
{
@@ -166,12 +183,6 @@ namespace Test.LightweightIocContainer
Assert.AreEqual(typeof(ITest), exception.Type);
}
- [Test]
- public void TestRegisterInterfaceWithoutImplementation()
- {
- Assert.Throws(() => _iocContainer.Register());
- }
-
[Test]
public void TestRegisterFactoryWithoutCreate()
{
@@ -185,6 +196,7 @@ namespace Test.LightweightIocContainer
}
[Test]
+ [Obsolete("RegisterUnitTestCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public void TestRegisterUnitTestCallback()
{
Assert.DoesNotThrow(() => _iocContainer.RegisterUnitTestCallback(delegate {return new Test(); }));
@@ -217,6 +229,13 @@ namespace Test.LightweightIocContainer
Assert.IsInstanceOf(resolvedTest);
}
+ [Test]
+ public void TestResolveInterfaceWithoutImplementation()
+ {
+ _iocContainer.Register();
+ Assert.Throws(() => _iocContainer.Resolve());
+ }
+
[Test]
public void TestResolveWithParams()
{
@@ -435,6 +454,7 @@ namespace Test.LightweightIocContainer
}
[Test]
+ [Obsolete("RegisterUnitTestCallback is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public void TestResolveUnitTestCallbackRegistration()
{
ITest callbackTest = new Test();
@@ -445,6 +465,17 @@ namespace Test.LightweightIocContainer
Assert.AreEqual(callbackTest, test);
}
+ [Test]
+ public void TestResolveSingleTypeRegistrationWithFactoryMethod()
+ {
+ _iocContainer.Register();
+ _iocContainer.Register().WithFactoryMethod(c => new TestConstructor(c.Resolve(), "someName"));
+
+ ITest test = _iocContainer.Resolve();
+
+ Assert.NotNull(test);
+ }
+
[Test]
public void TestIsTypeRegistered()
{
diff --git a/Test.LightweightIocContainer/RegistrationBaseTest.cs b/Test.LightweightIocContainer/RegistrationBaseTest.cs
new file mode 100644
index 0000000..b29afa7
--- /dev/null
+++ b/Test.LightweightIocContainer/RegistrationBaseTest.cs
@@ -0,0 +1,119 @@
+// Author: Gockner, Simon
+// Created: 2019-06-06
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using System;
+using JetBrains.Annotations;
+using LightweightIocContainer;
+using LightweightIocContainer.Exceptions;
+using LightweightIocContainer.Interfaces;
+using LightweightIocContainer.Interfaces.Registrations;
+using LightweightIocContainer.Registrations;
+using Moq;
+using NUnit.Framework;
+
+namespace Test.LightweightIocContainer
+{
+ [TestFixture]
+ public class RegistrationBaseTest
+ {
+ #region TestClasses
+
+ private interface ITest
+ {
+ void DoSomething();
+ }
+
+ private interface IFoo
+ {
+
+ }
+
+ private interface IBar
+ {
+
+ }
+
+ private class Test : ITest
+ {
+ public void DoSomething()
+ {
+ throw new Exception();
+ }
+ }
+
+ [UsedImplicitly]
+ private class Foo : IFoo
+ {
+ public Foo(IBar bar, ITest test)
+ {
+
+ }
+ }
+
+ private class Bar : IBar
+ {
+
+ }
+
+ #endregion
+
+
+ [Test]
+ public void TestOnCreate()
+ {
+ RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
+ IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).OnCreate(t => t.DoSomething());
+
+ ITest test = new Test();
+
+ Assert.Throws(() => testRegistration.OnCreateAction(test));
+ }
+
+ [Test]
+ public void TestWithParameters()
+ {
+ RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
+
+ IBar bar = new Bar();
+ ITest test = new Test();
+
+ IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters(bar, test);
+
+ Assert.AreEqual(bar, testRegistration.Parameters[0]);
+ Assert.AreEqual(test, testRegistration.Parameters[1]);
+ }
+
+ [Test]
+ public void TestWithParametersDifferentOrder()
+ {
+ RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
+
+ IBar bar = new Bar();
+ ITest test = new Test();
+
+ IRegistrationBase testRegistration = registrationFactory.Register(Lifestyle.Transient).WithParameters((0, bar), (3, test), (2, "SomeString"));
+
+ Assert.AreEqual(bar, testRegistration.Parameters[0]);
+ Assert.IsInstanceOf(testRegistration.Parameters[1]);
+ Assert.AreEqual("SomeString", testRegistration.Parameters[2]);
+ Assert.AreEqual(test, testRegistration.Parameters[3]);
+ }
+
+ [Test]
+ public void TestWithParametersCalledTwice()
+ {
+ RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
+ Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters(new Bar()).WithParameters(new Test()));
+ Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters((0, new Bar())).WithParameters((1, new Test())));
+ }
+
+ [Test]
+ public void TestWithParametersNoParametersGiven()
+ {
+ RegistrationFactory registrationFactory = new RegistrationFactory(new Mock().Object);
+ Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters((object[])null));
+ Assert.Throws(() => registrationFactory.Register(Lifestyle.Transient).WithParameters(((int index, object parameter)[])null));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs
new file mode 100644
index 0000000..b8bf268
--- /dev/null
+++ b/Test.LightweightIocContainer/SingleTypeRegistrationTest.cs
@@ -0,0 +1,61 @@
+// Author: Gockner, Simon
+// Created: 2019-11-22
+// Copyright(c) 2019 SimonG. All Rights Reserved.
+
+using JetBrains.Annotations;
+using LightweightIocContainer;
+using LightweightIocContainer.Interfaces;
+using LightweightIocContainer.Interfaces.Registrations;
+using LightweightIocContainer.Registrations;
+using Moq;
+using NUnit.Framework;
+
+namespace Test.LightweightIocContainer
+{
+ [TestFixture]
+ // ReSharper disable MemberHidesStaticFromOuterClass
+ public class SingleTypeRegistrationTest
+ {
+ private interface IFoo
+ {
+ IBar Bar { get; }
+ }
+
+ private interface IBar
+ {
+
+ }
+
+ [UsedImplicitly]
+ private class Foo : IFoo
+ {
+ public Foo(IBar bar)
+ {
+ Bar = bar;
+ }
+
+ public IBar Bar { get; }
+ }
+
+ [UsedImplicitly]
+ private class Bar : IBar
+ {
+
+ }
+
+ [Test]
+ public void TestSingleTypeRegistrationWithFactoryMethod()
+ {
+ IBar bar = new Bar();
+
+ Mock iocContainerMock = new Mock();
+ iocContainerMock.Setup(c => c.Resolve()).Returns(bar);
+
+ RegistrationFactory registrationFactory = new RegistrationFactory(iocContainerMock.Object);
+ ISingleTypeRegistration registration = registrationFactory.Register(Lifestyle.Transient).WithFactoryMethod(c => new Foo(c.Resolve()));
+
+ IFoo foo = registration.FactoryMethod(iocContainerMock.Object);
+ Assert.AreEqual(bar, foo.Bar);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Test.LightweightIocContainer/UnitTestCallbackRegistrationTest.cs b/Test.LightweightIocContainer/UnitTestCallbackRegistrationTest.cs
index 0e4a099..f9392db 100644
--- a/Test.LightweightIocContainer/UnitTestCallbackRegistrationTest.cs
+++ b/Test.LightweightIocContainer/UnitTestCallbackRegistrationTest.cs
@@ -2,6 +2,7 @@
// Created: 2019-10-15
// Copyright(c) 2019 SimonG. All Rights Reserved.
+using System;
using LightweightIocContainer;
using LightweightIocContainer.Interfaces;
using LightweightIocContainer.Interfaces.Registrations;
@@ -12,6 +13,7 @@ using NUnit.Framework;
namespace Test.LightweightIocContainer
{
[TestFixture]
+ [Obsolete("UnitTestCallbackRegistration is deprecated, use `WithFactoryMethod()` from ISingleTypeRegistration instead.")]
public class UnitTestCallbackRegistrationTest
{
private interface ITest