/// <summary>
        /// Constructs a <see cref="DelegateTarget"/> from the passed factory delegate (optionally with the given <paramref name="declaredType"/>,
        /// <paramref name="scopeBehaviour"/> and <paramref name="scopePreference"/>) and registers it in the target container.
        /// </summary>
        /// <param name="targetContainer">The target container in which the new target is to registered</param>
        /// <param name="factory">The factory delegate that is to be executed by the <see cref="DelegateTarget"/> that is created.</param>
        /// <param name="declaredType">Optional - if provided, then it overrides the <see cref="ITarget.DeclaredType"/> of the <see cref="DelegateTarget"/>
        /// that is created which, in turn, will change the type against which the target will be registered in the target container.  If null, then
        /// the return type of the factory will be used.</param>
        /// <param name="scopeBehaviour">Optional.  Controls how the object generated from the factory delegate will be
        /// tracked if the target is executed within an <see cref="ContainerScope" />.  The default is <see cref="ScopeBehaviour.None" /> - which means
        /// no disposal will take place.  Be careful with changing this - if the delegate produces new instances each time it's used, then
        /// <see cref="ScopeBehaviour.Implicit"/> is suitable; if not, then only <see cref="ScopeBehaviour.None"/> or <see cref="ScopeBehaviour.Explicit"/>
        /// are suitable.</param>
        /// <param name="scopePreference">Optional.  If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls the
        /// type of scope in which the instance should be tracked.  Defaults to <see cref="ScopePreference.Current"/>.  <see cref="ScopePreference.Root"/>
        /// should be used if the result of the delegate is effectively a singleton.</param>
        public static void RegisterDelegate(
            this ITargetContainer targetContainer,
            Delegate factory,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.Implicit,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            if (targetContainer == null)
            {
                throw new ArgumentNullException(nameof(targetContainer));
            }
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }

            ITarget toRegister = null;

            if (factory.GetMethodInfo().GetParameters()?.Length > 0)
            {
                toRegister = new DelegateTarget(factory, declaredType, scopeBehaviour: scopeBehaviour, scopePreference: scopePreference);
            }
            else
            {
                toRegister = new NullaryDelegateTarget(factory, declaredType, scopeBehaviour: scopeBehaviour, scopePreference: scopePreference);
            }

            targetContainer.Register(toRegister);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DelegateTarget" /> class.
        /// </summary>
        /// <param name="factory">Required - the factory delegate.  Must have a return type and can take
        /// 0 or more parameters.</param>
        /// <param name="declaredType">Optional - type that will be set into the <see cref="DeclaredType" /> for the target;
        /// if not provided, then it will be derived from the <paramref name="factory" />'s return type</param>
        /// <param name="scopeBehaviour">Scope behaviour for this delegate.  The default is <see cref="ScopeBehaviour.Implicit"/>, which means
        /// that that any returned instance will be tracked implicitly by the active scope.  If the delegate produces a new instance, then
        /// this or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
        /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
        /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
        /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
        /// <exception cref="ArgumentException">If the <paramref name="factory" /> represents a void delegate or if
        /// <paramref name="declaredType" /> is passed but the type is not compatible with the return type of
        /// <paramref name="factory" />.</exception>
        /// <exception cref="ArgumentNullException">If <paramref name="factory" /> is null</exception>
        public DelegateTarget(
            Delegate factory,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.Implicit,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }

            FactoryMethod = factory.GetMethodInfo();

            if (FactoryMethod.ReturnType == typeof(void))
            {
                throw new ArgumentException("Factory must have a return type", nameof(factory));
            }
            if (FactoryMethod.GetParameters().Any(p => p.ParameterType.IsByRef))
            {
                throw new ArgumentException("Delegates which have ref or out parameters are not permitted as the factory argument", nameof(factory));
            }

            if (declaredType != null)
            {
                if (!TypeHelpers.AreCompatible(FactoryMethod.ReturnType, declaredType) && !TypeHelpers.AreCompatible(declaredType, FactoryMethod.ReturnType))
                {
                    throw new ArgumentException(string.Format(ExceptionResources.DeclaredTypeIsNotCompatible_Format, declaredType, FactoryMethod.ReturnType), nameof(declaredType));
                }
            }

            this._declaredType    = declaredType;
            this._scopeBehaviour  = scopeBehaviour;
            this._scopePreference = scopePreference;
            Factory = factory;
        }
        /// <summary>
        /// Registers the expression in the target container
        /// </summary>
        /// <param name="targetContainer">The target container in which the registration will be made.</param>
        /// <param name="expression">The expression to be registered.</param>
        /// <param name="declaredType">Optional.  The <see cref="ITarget.DeclaredType"/> of the target to be created,
        /// if different from the <see cref="Expression.Type"/> of the <paramref name="expression"/> (or its
        /// <see cref="LambdaExpression.Body"/> if the expression is a <see cref="LambdaExpression"/>).
        ///
        /// Will also override the type against which the expression will be registered if provided.</param>
        /// <param name="scopeBehaviour">Optional.  Controls how the object generated from the compiled expression will be
        /// tracked if the target is executed within an <see cref="ContainerScope" />.  The default is <see cref="ScopeBehaviour.Implicit" />.</param>
        /// <param name="scopePreference">Optional.  If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls the
        /// type of scope in which the instance should be tracked.  Defaults to <see cref="ScopePreference.Current"/>.  <see cref="ScopePreference.Root"/>
        /// should be used if the result of the delegate is effectively a singleton.</param>
        public static void RegisterExpression(
            this ITargetContainer targetContainer,
            Expression expression,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.Implicit,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            if (targetContainer == null)
            {
                throw new ArgumentNullException(nameof(targetContainer));
            }

            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            ITarget toRegister = new ExpressionTarget(expression, declaredType);

            if (scopeBehaviour == ScopeBehaviour.Explicit)
            {
                toRegister = toRegister.Scoped();
            }
            else if (scopeBehaviour == ScopeBehaviour.None)
            {
                toRegister = toRegister.Unscoped();
            }

            targetContainer.Register(toRegister);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="ExpressionTarget"/> class.
 /// </summary>
 /// <param name="expressionFactory">Required. The factory delegate that a compiler should call to get the expression to use when
 /// compiling this target.</param>
 /// <param name="declaredType">Required. Static type of all expressions that will be
 /// returned by <paramref name="expressionFactory"/>.</param>
 /// <param name="scopeBehaviour">Scope behaviour for this expression.  The default is <see cref="ScopeBehaviour.Implicit"/>, which means
 /// that that any returned instance will be tracked implicitly by the active scope.  If the expression produces a new instance, then
 /// this or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
 /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
 /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
 /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
 public ExpressionTarget(
     Func <ICompileContext, Expression> expressionFactory,
     Type declaredType,
     ScopeBehaviour scopeBehaviour   = ScopeBehaviour.None,
     ScopePreference scopePreference = ScopePreference.Current)
 {
     ExpressionFactory = expressionFactory ?? throw new ArgumentNullException(nameof(expressionFactory));
     DeclaredType      = declaredType ?? throw new ArgumentNullException(nameof(declaredType));
     _scopeBehaviour   = scopeBehaviour;
     _scopePreference  = scopePreference;
 }
Exemple #5
0
        /// <summary>
        /// A simple wrapper for the <see cref="ExpressionTarget.ExpressionTarget(Expression, Type, ScopeBehaviour, ScopePreference)"/> constructor.
        /// </summary>
        /// <param name="expression">Required, the expression representing the code that is to be executed
        /// in order to produce an object.</param>
        /// <param name="declaredType">Optional.  If not null, then it will be used as the target's <see cref="ITarget.DeclaredType"/>
        /// which, in turn, is used as the target's default registration type if not overriden when added to an
        /// <see cref="ITargetContainer"/>.  If null, then the <see cref="Expression.Type"/> will be used, unless
        /// <paramref name="expression"/> is a <see cref="LambdaExpression"/>, in which case the <see cref="Expression.Type"/>
        /// of its <see cref="LambdaExpression.Body"/> will be used.</param>
        /// <param name="scopeBehaviour">Scope behaviour for this expression.  The default is <see cref="ScopeBehaviour.None"/>, which means
        /// that no disposal will take place by default for the instance.  If the expression produces a new instance, then
        /// <see cref="ScopeBehaviour.Implicit"/> or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
        /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
        /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
        /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
        /// <returns>An <see cref="ITarget"/> which represents the given expression; which must be compiled or otherwise
        /// translated into a runtime operation which creates/obtains an object.</returns>
        public static ITarget ForExpression(
            Expression expression,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.None,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            return(new ExpressionTarget(expression, declaredType, scopeBehaviour, scopePreference));
        }
Exemple #6
0
        /// <summary>
        /// A simple wrapper for the <see cref="DelegateTarget.DelegateTarget(Delegate, Type, ScopeBehaviour, ScopePreference)"/> constructor.
        /// </summary>
        /// <param name="factory">Required, the factory delegate that is to be used to produce an object.</param>
        /// <param name="declaredType">Optional.  If not null, then it will be used as the target's <see cref="ITarget.DeclaredType"/>
        /// which, in turn, is used as the target's default registration type if not overriden when added to
        /// an <see cref="ITargetContainer"/>.  If null, then the return type of the factory will be used.</param>
        /// <param name="scopeBehaviour">Scope behaviour for this delegate.  The default is <see cref="ScopeBehaviour.None"/>, which means
        /// that no disposal will take place by default for the instance.  If the delegate produces a new instance, then
        /// <see cref="ScopeBehaviour.Implicit"/> or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
        /// the delegate should produce one instance per scope, or should act as a disposable transient object.</param>
        /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
        /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
        /// <returns>An <see cref="ITarget"/> which represents the passed factory.</returns>
        public static ITarget ForDelegate(
            Delegate factory,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.None,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            if (factory == null)
            {
                throw new ArgumentNullException(nameof(factory));
            }

            return(new DelegateTarget(factory, declaredType));
        }
        public NullaryDelegateTarget(
            Delegate factory,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.Implicit,
            ScopePreference scopePreference = ScopePreference.Current)
            : base(factory, declaredType, scopeBehaviour, scopePreference)
        {
            if (FactoryMethod.GetParameters()?.Length > 0)
            {
                throw new ArgumentException("Only nullary delegates (i.e. which have no parameters) can be used for this target");
            }

            this._strongDelegate = Expression.Lambda <Func <object> >(Expression.Convert(
                                                                          Expression.Invoke(Expression.Constant(factory)), typeof(object))).Compile();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ExpressionTarget" /> class.
        /// </summary>
        /// <param name="expression">Required. The static expression which should be used by compilers.</param>
        /// <param name="declaredType">Declared type of the target to be created (used when registering without
        /// an explicit type or when this target is used as a value inside another target).</param>
        /// <param name="scopeBehaviour">Scope behaviour for this expression.  The default is <see cref="ScopeBehaviour.Implicit"/>, which means
        /// that that any returned instance will be tracked implicitly by the active scope.  If the expression produces a new instance, then
        /// this or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
        /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
        /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
        /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
        /// <remarks><paramref name="declaredType"/> will automatically be determined if not provided
        /// by examining the type of the <paramref name="expression"/>.  For lambdas, the type will
        /// be derived from the Type of the lambda's body.  For all other expressions, the type is
        /// taken directly from the Type property of the expression itself.</remarks>
        public ExpressionTarget(
            Expression expression,
            Type declaredType               = null,
            ScopeBehaviour scopeBehaviour   = ScopeBehaviour.None,
            ScopePreference scopePreference = ScopePreference.Current)
        {
            Expression = expression ?? throw new ArgumentNullException(nameof(expression));
            var expressionType = (expression.NodeType == ExpressionType.Lambda ? ((LambdaExpression)expression).Body.Type : expression.Type);

            DeclaredType = declaredType ?? expressionType;

            if (!DeclaredType.IsAssignableFrom(expressionType))
            {
                throw new ArgumentException($"{nameof(declaredType)} must be compatible with the type of the expression", nameof(declaredType));
            }
        }
Exemple #9
0
        /// <summary>
        /// Creates a new instance of the <see cref="ObjectTarget"/> class.
        /// </summary>
        /// <param name="obj">The object to be returned by this target when resolved.</param>
        /// <param name="declaredType">Optional.  The declared type of this target, if different from the absolute type of the <paramref name="obj"/></param>
        /// <param name="scopeBehaviour">Optional.  If you want the object to be disposed by Rezolver when the root scope is disposed, then
        /// specify a behaviour other than the default.  Note - the only real behaviour that makes sense for this is <see cref="ScopeBehaviour.Explicit"/>,
        /// since the Implicit behaviour will typically fool a scope that multiple instances are being created and, therefore, the object
        /// will be tracked multiple times by that scope.</param>
        /// <remarks>Please note - if you enable scope tracking, but the object is never resolved, then the object will not be disposed and you will need
        /// to ensure you dispose of it.</remarks>
        public ObjectTarget(object obj, Type declaredType = null, ScopeBehaviour scopeBehaviour = Rezolver.ScopeBehaviour.None)
        {
            Value          = obj;
            ScopeBehaviour = scopeBehaviour;
            // if the caller provides a declared type we check
            // also that, if the object is null, the target type
            // can accept nulls.  Otherwise we're simply checking
            // that the value that's supplied is compatible with the
            // type that is being declared.
            if (declaredType != null)
            {
                if (Value == null)
                {
                    if (!declaredType.CanBeNull())
                    {
                        throw new ArgumentException(string.Format(ExceptionResources.TargetIsNullButTypeIsNotNullable_Format, declaredType), "declaredType");
                    }
                }
                else if (!TypeHelpers.AreCompatible(Value.GetType(), declaredType))
                {
                    throw new ArgumentException(string.Format(ExceptionResources.DeclaredTypeIsNotCompatible_Format, declaredType, Value.GetType()), "declaredType");
                }

                DeclaredType = declaredType;
            }
            else // an untyped null is typed as Object
            {
                DeclaredType = Value == null ? typeof(object) : Value.GetType();
            }

            switch (ScopeBehaviour)
            {
            case ScopeBehaviour.None:
                _factory = (ResolveContext context) => Value;
                break;

            case ScopeBehaviour.Implicit:
                _factory = (ResolveContext context) => context.ActivateImplicit_RootScope(Value);
                break;

            case ScopeBehaviour.Explicit:
                Func <ResolveContext, object> activation = (ResolveContext cc) => Value;
                _factory = (ResolveContext context) => context.ActivateExplicit_RootScope(this.Id, activation);
                break;
            }
        }
Exemple #10
0
 /// <summary>Creates a <see cref="Rezolver.Targets.DelegateTarget" /> for a factory delegate which takes 3 arguments
 /// and which returns an instance of <typeparamref name="TResult" /></summary>
 /// <typeparam name="T1">Type of the 1st delegate parameter</typeparam>
 /// <typeparam name="T2">Type of the 2nd delegate parameter</typeparam>
 /// <typeparam name="T3">Type of the 3rd delegate parameter</typeparam>
 /// <typeparam name="TResult">The type of the object produced by the factory delegate.</typeparam>
 /// <param name="factory">Required.  The factory delegate that is to be wrapped by the target.</param>
 /// <param name="declaredType">Optional.  The <see cref="ITarget.DeclaredType" /> of the target to be created,
 /// if different from <typeparamref name="TResult" /></param>
 /// <param name="scopeBehaviour">Optional.  The type of disposal tracking to be employed by this target.  Defaults to <see cref="ScopeBehaviour.Implicit" />.</param>
 /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
 /// <remarks>All arguments to the delegate are injected from the container when executed</remarks>
 public static ITarget ForDelegate <T1, T2, T3, TResult>(Func <T1, T2, T3, TResult> factory, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.Implicit, ScopePreference scopePreference = ScopePreference.Current)
 {
     if (factory == null)
     {
         throw new ArgumentNullException(nameof(factory));
     }
     return(new DelegateTarget(factory, declaredType, scopeBehaviour, scopePreference));
 }
Exemple #11
0
 /// <summary>Registers a <see cref="Rezolver.Targets.DelegateTarget" /> built from a factory delegate which takes 5 arguments
 /// and which returns an instance of <typeparamref name="TResult" /></summary>
 /// <typeparam name="T1">Type of the 1st delegate parameter</typeparam>
 /// <typeparam name="T2">Type of the 2nd delegate parameter</typeparam>
 /// <typeparam name="T3">Type of the 3rd delegate parameter</typeparam>
 /// <typeparam name="T4">Type of the 4th delegate parameter</typeparam>
 /// <typeparam name="T5">Type of the 5th delegate parameter</typeparam>
 /// <typeparam name="TResult">The type of the object produced by the factory delegate.</typeparam>
 /// <param name="targets">Required.  The <see cref="ITargetContainer" /> into which the newly created target will be registered</param>
 /// <param name="factory">Required.  The factory delegate which is to be executed when an instance is resolved by a container</param>
 /// <param name="declaredType">Optional.  The <see cref="ITarget.DeclaredType" /> of the target to be created
 /// if different from <typeparamref name="TResult" />.  Also overrides the type against which the registration will be made.</param>
 /// <param name="scopeBehaviour">Optional.  Controls how the object generated from the factory delegate will be
 /// tracked if the target is executed within an <see cref="ContainerScope" />.  The default is <see cref="ScopeBehaviour.Implicit" />.</param>
 /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
 public static void RegisterDelegate <T1, T2, T3, T4, T5, TResult>(this ITargetContainer targets, Func <T1, T2, T3, T4, T5, TResult> factory, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.Implicit, ScopePreference scopePreference = ScopePreference.Current)
 {
     targets.RegisterDelegate((Delegate)factory, declaredType, scopeBehaviour, scopePreference);
 }
Exemple #12
0
 /// <summary>
 /// Creates a new <see cref="ObjectTarget"/> for the passed <paramref name="object"/> whose
 /// <see cref="ITarget.DeclaredType"/> will either be set to object's type (obtained by calling
 /// <see cref="object.GetType"/> or <paramref name="declaredType"/>, if it is passed non-null.
 /// </summary>
 /// <param name="object">The @object to be wrapped by the new <see cref="ObjectTarget"/></param>
 /// <param name="declaredType">Optional - will be used to set the <see cref="ITarget.DeclaredType"/>
 /// of the target that is created.</param>
 /// <param name="scopeBehaviour">The scope behaviour of the target if resolved inside an
 /// <see cref="ContainerScope"/>.</param>
 public static ITarget ForObject(object @object, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.None)
 {
     return(new ObjectTarget(@object, declaredType ?? @object?.GetType(), scopeBehaviour));
 }
Exemple #13
0
 /// <summary>
 /// Creates a new <see cref="ObjectTarget"/> for the passed <paramref name="object"/> whose
 /// <see cref="ITarget.DeclaredType"/> will either be set to <typeparamref name="T"/> or
 /// <paramref name="declaredType"/>, if it is passed non-null.
 /// </summary>
 /// <typeparam name="T">Type of the object</typeparam>
 /// <param name="object">The @object to be wrapped by the new <see cref="ObjectTarget"/></param>
 /// <param name="declaredType">Optional - will be used to set the <see cref="ITarget.DeclaredType"/>
 /// of the target that is created.</param>
 /// <param name="scopeBehaviour">The scope behaviour of the target if resolved inside an
 /// <see cref="ContainerScope"/>.</param>
 public static ITarget ForObject <T>(T @object, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.None)
 {
     return(new ObjectTarget(@object, declaredType ?? typeof(T), scopeBehaviour));
 }
Exemple #14
0
 /// <summary>
 /// Registers an instance to be used when resolve a particular service type via the <see cref="ObjectTarget"/>
 /// </summary>
 /// <param name="targetContainer">The target container which will receive the registration.</param>
 /// <param name="obj">Required, but can be <c>null</c>.  The instance that will be resolved when the service type is requested.</param>
 /// <param name="declaredType">Type to be set as the <see cref="ITarget.DeclaredType"/> of the <see cref="ObjectTarget"/>
 /// that is created for <paramref name="obj"/>, if different from the object's type.</param>
 /// <param name="serviceType">The service type against which this object is to be registered, if different
 /// from <paramref name="declaredType"/> (or the object's type).</param>
 /// <param name="scopeBehaviour">Sets the <see cref="ITarget.ScopeBehaviour"/> for the <see cref="ObjectTarget"/> that's created</param>
 /// <remarks><c>null</c> objects are implicitly treated as <see cref="System.Object"/> if <paramref name="declaredType"/> is not passed.</remarks>
 public static void RegisterObject(this ITargetContainer targetContainer, object obj, Type declaredType = null, Type serviceType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.None)
 {
     if (targetContainer == null)
     {
         throw new ArgumentNullException(nameof(targetContainer));
     }
     targetContainer.Register(Target.ForObject(obj, declaredType ?? obj?.GetType(), scopeBehaviour: scopeBehaviour), serviceType ?? declaredType ?? obj?.GetType());
 }
 /// <summary>Creates an <see cref="Rezolver.Targets.ExpressionTarget" /> for a lambda expression which takes 2 arguments
 /// and which returns an instance of <typeparamref name="TResult" /></summary>
 /// <typeparam name="T1">Type of the 1st parameter of the lambda expression.</typeparam>
 /// <typeparam name="T2">Type of the 2nd parameter of the lambda expression.</typeparam>
 /// <typeparam name="TResult">The return type of the lambda expression.</typeparam>
 /// <param name="lambda">Required.  The lambda expression that is to be wrapped by the target.</param>
 /// <param name="declaredType">Optional.  The <see cref="ITarget.DeclaredType" /> of the target to be created,
 /// if different from <typeparamref name="TResult" /></param>
 /// <param name="scopeBehaviour">Scope behaviour for this expression.  The default is <see cref="ScopeBehaviour.Implicit"/>, which means
 /// that that any returned instance will be tracked implicitly by the active scope.  If the expression produces a new instance, then
 /// this or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
 /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
 /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
 /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
 /// <remarks>All arguments to the lambda are injected from the container when compiled and executed</remarks>
 public static ITarget ForExpression <T1, T2, TResult>(Expression <Func <T1, T2, TResult> > lambda, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.Implicit, ScopePreference scopePreference = ScopePreference.Current)
 {
     if (lambda == null)
     {
         throw new ArgumentNullException(nameof(lambda));
     }
     return(new ExpressionTarget(lambda, declaredType, scopeBehaviour, scopePreference));
 }
 /// <summary>Registers an <see cref="Rezolver.Targets.ExpressionTarget" /> built from a lambda expression which takes 5 arguments
 /// and which returns an instance of <typeparamref name="TResult" /></summary>
 /// <typeparam name="T1">Type of the 1st parameter of the lambda expression.</typeparam>
 /// <typeparam name="T2">Type of the 2nd parameter of the lambda expression.</typeparam>
 /// <typeparam name="T3">Type of the 3rd parameter of the lambda expression.</typeparam>
 /// <typeparam name="T4">Type of the 4th parameter of the lambda expression.</typeparam>
 /// <typeparam name="T5">Type of the 5th parameter of the lambda expression.</typeparam>
 /// <typeparam name="TResult">The return type of the lambda expression.</typeparam>
 /// <param name="targets">Required.  The <see cref="ITargetContainer" /> into which the newly created target will be registered</param>
 /// <param name="lambda">Required.  The lambda expression which is to be compiled and executed when an instance is resolved by a container</param>
 /// <param name="declaredType">Optional.  The <see cref="ITarget.DeclaredType" /> of the target to be created
 /// if different from <typeparamref name="TResult" />.  Also overrides the type against which the registration will be made.</param>
 /// <param name="scopeBehaviour">Scope behaviour for this expression.  The default is <see cref="ScopeBehaviour.Implicit"/>, which means
 /// that that any returned instance will be tracked implicitly by the active scope.  If the expression produces a new instance, then
 /// this or <see cref="ScopeBehaviour.Explicit"/> can be used safely - the choice being whether
 /// the expression should produce one instance per scope, or should act as a disposable transient object.</param>
 /// <param name="scopePreference">If <paramref name="scopeBehaviour"/> is not <see cref="ScopeBehaviour.None"/>, then this controls
 /// the preferred scope for the instance to be tracked.  Defaults to <see cref="ScopePreference.Current"/></param>
 /// <remarks>All arguments to the lambda are injected from the container when compiled and executed</remarks>
 public static void RegisterExpression <T1, T2, T3, T4, T5, TResult>(this ITargetContainer targets, Expression <Func <T1, T2, T3, T4, T5, TResult> > lambda, Type declaredType = null, ScopeBehaviour scopeBehaviour = ScopeBehaviour.Implicit, ScopePreference scopePreference = ScopePreference.Current)
 {
     targets.RegisterExpression((Expression)lambda, declaredType, scopeBehaviour, scopePreference);
 }