/// <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; }
/// <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)); }
/// <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)); } }
/// <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; } }
/// <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)); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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); }