diff --git a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs index d106bbf..7f7e3dd 100644 --- a/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs +++ b/LightweightIocContainer/Interfaces/Registrations/IRegistrationBase.cs @@ -3,6 +3,7 @@ // Copyright(c) 2019 SimonG. All Rights Reserved. using System; +using LightweightIocContainer.Exceptions; using LightweightIocContainer.Interfaces.Installers; namespace LightweightIocContainer.Interfaces.Registrations @@ -30,5 +31,30 @@ namespace LightweightIocContainer.Interfaces.Registrations /// 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/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 8096bf9..dd6b580 100644 --- a/LightweightIocContainer/IocContainer.cs +++ b/LightweightIocContainer/IocContainer.cs @@ -312,6 +312,9 @@ namespace LightweightIocContainer /// A newly created instance of the given private T CreateInstance(IRegistrationBase registration, object[] arguments, List resolveStack) { + if (registration.Parameters != null) + arguments = UpdateArgumentsWithRegistrationParameters(registration, arguments); + T instance; if (registration is IDefaultRegistration defaultRegistration) { @@ -339,6 +342,50 @@ namespace LightweightIocContainer 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 /// @@ -456,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/LightweightIocContainer.xml b/LightweightIocContainer/LightweightIocContainer.xml index b82fb77..067c4f7 100644 --- a/LightweightIocContainer/LightweightIocContainer.xml +++ b/LightweightIocContainer/LightweightIocContainer.xml @@ -456,6 +456,30 @@ The The current instance of this + + + An of parameters that are used to an instance of this + Can be set in the by calling + + + + + Pass parameters that will be used to an instance of this + Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving + + The parameters + The current instance of this + are already set or no parameters given + + + + Pass parameters that will be used to an instance of this + Parameters set with this method are inserted at the position in the argument list that is passed with the parameter if more parameters are given when resolving + + The parameters with their position + The current instance of this + are already set or no parameters given + The to register either only an interface or only a @@ -496,6 +520,11 @@ 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 @@ -629,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 @@ -657,11 +695,6 @@ The method - - - An internal placeholder that is used during the resolving process - - The Lifestyles that can be used for a @@ -761,6 +794,30 @@ The The current instance of this + + + An of parameters that are used to an instance of this + Can be set in the by calling + + + + + Pass parameters that will be used to an instance of this + Parameters set with this method are always inserted at the beginning of the argument list if more parameters are given when resolving + + The parameters + The current instance of this + are already set or no parameters given + + + + 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 diff --git a/LightweightIocContainer/Registrations/RegistrationBase.cs b/LightweightIocContainer/Registrations/RegistrationBase.cs index 3c77b39..512fed9 100644 --- a/LightweightIocContainer/Registrations/RegistrationBase.cs +++ b/LightweightIocContainer/Registrations/RegistrationBase.cs @@ -3,6 +3,9 @@ // 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; @@ -58,5 +61,59 @@ namespace LightweightIocContainer.Registrations 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