예제 #1
0
        /// <summary>
        /// Create enumerable expression using a custom creator
        /// </summary>
        /// <param name="scope">injection scope</param>
        /// <param name="request">expression request</param>
        /// <param name="arrayExpressionCreator">array creator</param>
        /// <param name="enumerableCreator">custom enumerable creator</param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult CreateEnumerableExpressionUsingCustomCreator(IInjectionScope scope,
                                                                                                   IActivationExpressionRequest request, IArrayExpressionCreator arrayExpressionCreator,
                                                                                                   IEnumerableCreator enumerableCreator)
        {
            var enumerableType = request.ActivationType.GenericTypeArguments[0];

            var arrayType = enumerableType.MakeArrayType();

            var newRequest =
                request.NewRequest(arrayType, request.RequestingStrategy,
                                   request.RequestingStrategy?.ActivationType, request.RequestType, request.Info, true, true);

            newRequest.SetFilter(request.Filter);
            newRequest.SetEnumerableComparer(request.EnumerableComparer);

            var arrayExpression = arrayExpressionCreator.GetArrayExpression(scope, newRequest);

            request.RequireExportScope();

            var enumerableExpression =
                Expression.Call(Expression.Constant(enumerableCreator),
                                CreateEnumerableMethod.MakeGenericMethod(enumerableType),
                                request.ScopeParameter,
                                arrayExpression.Expression);

            var returnResult = request.Services.Compiler.CreateNewResult(request, enumerableExpression);

            returnResult.AddExpressionResult(returnResult);

            return(returnResult);
        }
예제 #2
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public override IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var closedClass = typeof(LazyExpression <,>).MakeGenericType(request.ActivationType.GenericTypeArguments);

            var closedMethod = closedClass.GetRuntimeMethod(nameof(LazyExpression <object, object> .CreateLazy), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) });

            var wrappedStrategy = request.GetWrappedStrategy();

            if (wrappedStrategy == null)
            {
                throw new LocateException(request.GetStaticInjectionContext(), "Could not find strategy that is wrapped");
            }

            var metadata = _strongMetadataInstanceProvider.GetMetadata(request.ActivationType.GenericTypeArguments[1],
                                                                       wrappedStrategy.Metadata);

            var instance = Activator.CreateInstance(closedClass, scope, request, this, metadata);

            request.RequireExportScope();
            request.RequireDisposalScope();

            var callExpression =
                Expression.Call(Expression.Constant(instance), closedMethod, request.ScopeParameter,
                                request.DisposalScopeExpression, request.InjectionContextParameter);

            request.RequireInjectionContext();

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #3
0
        /// <summary>Visits the children of the <see cref="T:System.Linq.Expressions.MethodCallExpression" />.</summary>
        /// <returns>The modified expression, if it or any subexpression was modified; otherwise, returns the original expression.</returns>
        /// <param name="node">The expression to visit.</param>
        protected override Expression VisitMethodCall(MethodCallExpression node)
        {
            if (node.Method.DeclaringType == typeof(Arg))
            {
                var methodName = node.Method.Name;

                if (methodName == nameof(Arg.Any) ||
                    methodName == nameof(Arg.Locate))
                {
                    var newRequest = _request.NewRequest(node.Method.GetGenericArguments().First(), _activationStrategy,
                                                         _activationStrategy.ActivationType, RequestType.Other, null, true, true);

                    var arguement = node.Arguments.FirstOrDefault();

                    if (arguement != null)
                    {
                        var replaceNode = (MethodCallExpression)base.VisitMethodCall(node);

                        arguement = replaceNode.Arguments.First();

                        if (arguement is NewExpression newExpression)
                        {
                            var parameters = newExpression.Constructor.GetParameters();

                            for (int i = 0; i < parameters.Length; i++)
                            {
                                var expression = newExpression.Arguments[i];
                                var parameter  = parameters[i];

                                var knownValue = new SimpleKnownValueExpression(expression.Type, expression,
                                                                                parameter.Name);

                                newRequest.AddKnownValueExpression(knownValue);
                            }
                        }
                    }

                    var activationExpression =
                        _request.Services.ExpressionBuilder.GetActivationExpression(_request.RequestingScope, newRequest);

                    _result.AddExpressionResult(activationExpression);

                    return(activationExpression.Expression);
                }

                if (methodName == nameof(Arg.Scope))
                {
                    _request.RequireExportScope();

                    return(_request.ScopeParameter);
                }

                if (methodName == nameof(Arg.Context))
                {
                    return(_request.InjectionContextParameter);
                }
            }

            return(base.VisitMethodCall(node));
        }
예제 #4
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public IActivationExpressionResult GetActivationExpression(IInjectionScope scope,
                                                                   IActivationExpressionRequest request)
        {
            Expression          assignStatement = null;
            ParameterExpression newScope        = null;

            if (ActivationConfiguration.CustomScopeName != null)
            {
                request.RequireExportScope();

                newScope = Expression.Variable(typeof(IExportLocatorScope));

                var beginScopeMethod =
                    typeof(IExportLocatorScope).GetTypeInfo().GetDeclaredMethod(nameof(IExportLocatorScope.BeginLifetimeScope));

                assignStatement =
                    Expression.Assign(newScope,
                                      Expression.Call(request.ScopeParameter, beginScopeMethod,
                                                      Expression.Constant(ActivationConfiguration.CustomScopeName)));

                request.ScopeParameter = newScope;
            }

            var result = request.Services.ExpressionBuilder.DecorateExportStrategy(scope, request, this) ??
                         _builder.GetActivationExpression(scope, request, ActivationConfiguration, ActivationConfiguration.Lifestyle);

            if (newScope != null)
            {
                result.AddExtraParameter(newScope);
                result.AddExtraExpression(assignStatement, true);
            }

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var openMethod = typeof(KeyedLocateDelegateStrategy).GetRuntimeMethod(nameof(CreateKeyedDelegate),
                                                                                  new[] { typeof(IExportLocatorScope) });

            var closedMethod = openMethod.MakeGenericMethod(request.ActivationType.GenericTypeArguments);

            request.RequireExportScope();

            var expression = Expression.Call(null, closedMethod, request.ScopeParameter);

            return(request.Services.Compiler.CreateNewResult(request, expression));
        }
        /// <summary>
        /// get activation strategy delegate
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public override IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var closedClass = typeof(TypedDelegateExpression <>).MakeGenericType(request.ActivationType.GenericTypeArguments);

            var closedMethod = closedClass.GetRuntimeMethod(nameof(TypedDelegateExpression <object> .CreateFunc), new Type[] {  });

            var instance = Activator.CreateInstance(closedClass, scope, request, this);

            request.RequireExportScope();
            request.RequireDisposalScope();

            var callExpression =
                Expression.Call(Expression.Constant(instance), closedMethod);

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #7
0
        /// <summary>
        /// Create instantiation expression
        /// </summary>
        /// <param name="scope">scope the configuration is associated with</param>
        /// <param name="request">expression request</param>
        /// <param name="activationConfiguration">configuration</param>
        /// <returns>expression result</returns>
        public override IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request,
                                                                     TypeActivationConfiguration activationConfiguration)
        {
            request.RequireExportScope();

            // manipulate scope parameter rather
            var currentScope = request.ScopeParameter;

            request.ScopeParameter = request.Constants.ScopeParameter;

            var activationDelegate = CreateActivationDelegate(scope, request, activationConfiguration);

            request.ScopeParameter = currentScope;

            return(CreateCallExpression(scope, request, activationConfiguration, activationDelegate));
        }
예제 #8
0
        /// <summary>
        /// Provide an expression that uses the lifestyle
        /// </summary>
        /// <param name="scope">scope for the strategy</param>
        /// <param name="request">activation request</param>
        /// <param name="activationExpression">expression to create strategy type</param>
        /// <returns></returns>
        public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression)
        {
            var context = request.GetStaticInjectionContext();

            var ancestorId  = GetAncestorRequestId(context);
            var newDelegate = request.Services.Compiler.CompileDelegate(scope, activationExpression(request));

            MethodInfo closedMethod;

            if (_guaranteeOnlyOne)
            {
                var openMethod = typeof(SingletonPerAncestor).GetRuntimeMethod(nameof(GetValueGuaranteeOnce),
                                                                               new[]
                {
                    typeof(IExportLocatorScope),
                    typeof(IDisposalScope),
                    typeof(IInjectionContext),
                    typeof(ActivationStrategyDelegate),
                    typeof(string)
                });

                closedMethod = openMethod.MakeGenericMethod(request.ActivationType);
            }
            else
            {
                var openMethod = typeof(SingletonPerAncestor).GetRuntimeMethod(nameof(GetValue),
                                                                               new[]
                {
                    typeof(IExportLocatorScope),
                    typeof(IDisposalScope),
                    typeof(IInjectionContext),
                    typeof(ActivationStrategyDelegate),
                    typeof(string)
                });

                closedMethod = openMethod.MakeGenericMethod(request.ActivationType);
            }

            var expression = Expression.Call(closedMethod, request.ScopeParameter,
                                             request.DisposalScopeExpression, request.InjectionContextParameter,
                                             Expression.Constant(newDelegate), Expression.Constant(ancestorId));

            request.RequireInjectionContext();
            request.RequireExportScope();

            return(request.Services.Compiler.CreateNewResult(request, expression));
        }
예제 #9
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var activationType = request.ActivationType;

            var closedType = ReflectionHelper.CreateClosedExportTypeFromRequestingType(ActivationType, activationType);

            if (closedType == null)
            {
                return(null);
            }

            var activation = GetActivationConfiguration(closedType);

            scope.ScopeConfiguration.Trace?.Invoke($"Activating {closedType.FullName} with lifestyle '{Lifestyle}' for request type {activationType.FullName}");


            Expression          assignStatement = null;
            ParameterExpression newScope        = null;

            if (ActivationConfiguration.CustomScopeName != null)
            {
                request.RequireExportScope();

                newScope = Expression.Variable(typeof(IExportLocatorScope));

                var beginScopeMethod =
                    typeof(IExportLocatorScope).GetTypeInfo().GetDeclaredMethod(nameof(IExportLocatorScope.BeginLifetimeScope));

                assignStatement =
                    Expression.Assign(newScope,
                                      Expression.Call(request.ScopeParameter, beginScopeMethod,
                                                      Expression.Constant(ActivationConfiguration.CustomScopeName)));

                request.ScopeParameter = newScope;
            }

            var result = request.Services.ExpressionBuilder.DecorateExportStrategy(scope, request, this) ??
                         _builder.GetActivationExpression(scope, request, activation, activation.Lifestyle);

            if (newScope != null)
            {
                result.AddExtraParameter(newScope);
                result.AddExtraExpression(assignStatement, true);
            }

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public override IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var closedClass = typeof(FuncExpression <, , ,>).MakeGenericType(request.ActivationType.GenericTypeArguments);

            var closedMethod = closedClass.GetRuntimeMethod(nameof(FuncExpression <object, object, object, object> .CreateFunc), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) });

            var instance = Activator.CreateInstance(closedClass, scope, request, request.Services.InjectionContextCreator, this);

            request.RequireExportScope();
            request.RequireDisposalScope();

            var callExpression =
                Expression.Call(Expression.Constant(instance), closedMethod, request.ScopeParameter,
                                request.DisposalScopeExpression, request.InjectionContextParameter);

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #11
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            Expression expression;

            request.RequireExportScope();

            if (_func.Target != null)
            {
                expression = Expression.Call(Expression.Constant(_func.Target), _func.GetMethodInfo(),
                                             request.ScopeParameter);
            }
            else
            {
                expression = Expression.Call(_func.GetMethodInfo(), request.ScopeParameter);
            }

            return(request.Services.Compiler.CreateNewResult(request, expression));
        }
예제 #12
0
        /// <summary>
        /// Creates expression for calling method GetValueFromInjectionContext
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public virtual IActivationExpressionResult GetValueFromInjectionContext(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var valueMethod = _contextValueProvider.GetType().GetRuntimeMethod(nameof(GetValueFromInjectionContext), new[]
            {
                typeof(IExportLocatorScope),
                typeof(StaticInjectionContext),
                typeof(object),
                typeof(IInjectionContext),
                typeof(object),
                typeof(bool),
                typeof(bool)
            });

            var closedMethod = valueMethod.MakeGenericMethod(request.ActivationType);

            var key = request.LocateKey;

            if (key is string)
            {
                key = ((string)key).ToLowerInvariant();
            }

            request.RequireExportScope();

            var expression = Expression.Call(Expression.Constant(_contextValueProvider),
                                             closedMethod,
                                             request.ScopeParameter,
                                             Expression.Constant(request.GetStaticInjectionContext()),
                                             Expression.Constant(key, typeof(object)),
                                             request.InjectionContextParameter,
                                             Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object)),
                                             Expression.Constant(request.DefaultValue != null),
                                             Expression.Constant(request.IsRequired));

            var result = request.Services.Compiler.CreateNewResult(request, expression);

            result.UsingFallbackExpression = true;

            return(result);
        }
예제 #13
0
        /// <summary>
        /// Provide an expression that uses the lifestyle
        /// </summary>
        /// <param name="scope">scope for the strategy</param>
        /// <param name="request">activation request</param>
        /// <param name="activationExpression">expression to create strategy type</param>
        /// <returns></returns>
        public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression)
        {
            if (CompiledDelegate == null)
            {
                // new request as we don't want to carry any info over from parent request
                var newRequest = request.NewRootedRequest(request.ActivationType, scope, true);

                var localDelegate = request.Services.Compiler.CompileDelegate(scope, activationExpression(newRequest));

                Interlocked.CompareExchange(ref CompiledDelegate, localDelegate, null);
            }

            var getValueFromScopeMethod =
                typeof(SingletonPerNamedScopeLifestyle).GetRuntimeMethod(nameof(GetValueFromScope),
                                                                         new[]
            {
                typeof(IExportLocatorScope),
                typeof(ActivationStrategyDelegate),
                typeof(string),
                typeof(string),
                typeof(bool),
                typeof(IInjectionContext),
                typeof(StaticInjectionContext)
            });

            var closedMethod = getValueFromScopeMethod.MakeGenericMethod(request.ActivationType);

            var expression = Expression.Call(closedMethod,
                                             request.ScopeParameter,
                                             Expression.Constant(CompiledDelegate),
                                             Expression.Constant(UniqueId),
                                             Expression.Constant(_scopeName),
                                             Expression.Constant(scope.ScopeConfiguration.SingletonPerScopeShareContext),
                                             request.InjectionContextParameter,
                                             Expression.Constant(request.GetStaticInjectionContext()));

            request.RequireExportScope();

            return(request.Services.Compiler.CreateNewResult(request, expression));
        }
예제 #14
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public override IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            var invokeMethod = request.ActivationType.GetTypeInfo().GetDeclaredMethod("Invoke");

            var list = new List <Type>(invokeMethod.GetParameters().Select(p => p.ParameterType));

            list.Add(invokeMethod.ReturnType);
            list.Add(request.ActivationType);

            var closedClass = typeof(DelegateExpression <, ,>).MakeGenericType(list.ToArray());

            var closedMethod = closedClass.GetRuntimeMethod(nameof(DelegateExpression <object, object, object> .CreateDelegate), new[] { typeof(IExportLocatorScope), typeof(IDisposalScope), typeof(IInjectionContext) });

            var instance = Activator.CreateInstance(closedClass, scope, request, request.Services.InjectionContextCreator, this);

            request.RequireExportScope();
            request.RequireDisposalScope();

            var callExpression =
                Expression.Call(Expression.Constant(instance), closedMethod, request.ScopeParameter,
                                request.DisposalScopeExpression, request.InjectionContextParameter);

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #15
0
        /// <summary>
        /// Provide an expression that uses the lifestyle
        /// </summary>
        /// <param name="scope">scope for the strategy</param>
        /// <param name="request">activation request</param>
        /// <param name="activationExpression">expression to create strategy type</param>
        /// <returns></returns>
        public virtual IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request, Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression)
        {
            var local = request.PerDelegateData.GetExtraDataOrDefaultValue <ParameterExpression>("local" + UniqueId);

            if (local != null)
            {
                return(request.Services.Compiler.CreateNewResult(request, local));
            }

            request.RequireExportScope();

            if (CompiledDelegate == null)
            {
                // new request as we don't want to carry any info over from parent request
                var newRequest = request.NewRootedRequest(request.ActivationType, scope, true);

                var newResult = activationExpression(newRequest);

                Delegate localDelegate = null;

                if (ThreadSafe || newRequest.ExportScopeRequired() || newRequest.DisposalScopeRequired() ||
                    newRequest.InjectionContextRequired())
                {
                    localDelegate = request.Services.Compiler.CompileDelegate(scope, newResult);
                }
                else
                {
                    var openMethod = GetType().GetTypeInfo().GetDeclaredMethod(nameof(CompileFuncDelage));

                    var closed = openMethod.MakeGenericMethod(newResult.Expression.Type);

                    localDelegate = (Delegate)closed.Invoke(null, new object[] { request, scope, newResult });
                }

                Interlocked.CompareExchange(ref CompiledDelegate, localDelegate, null);
            }

            Expression createExpression;

            if (ThreadSafe)
            {
                var getValueFromScopeMethod = typeof(SingletonPerScopeLifestyle).GetRuntimeMethod(nameof(GetValueFromScopeThreadSafe), new[]
                {
                    typeof(IExportLocatorScope),
                    typeof(ActivationStrategyDelegate),
                    typeof(string),
                    typeof(bool),
                    typeof(IInjectionContext)
                });

                var closedMethod = getValueFromScopeMethod.MakeGenericMethod(request.ActivationType);

                createExpression = Expression.Call(closedMethod,
                                                   request.ScopeParameter,
                                                   Expression.Constant(CompiledDelegate),
                                                   Expression.Constant(UniqueId),
                                                   Expression.Constant(scope.ScopeConfiguration.SingletonPerScopeShareContext),
                                                   request.InjectionContextParameter);
            }
            else
            {
                var invokeMethodFastLane = CompiledDelegate.GetMethodInfo().GetParameters().Length < 3;

                if (invokeMethodFastLane)
                {
                    var getOrCreateMethod = typeof(IExportLocatorScope).GetTypeInfo()
                                            .GetDeclaredMethods(nameof(IExportLocatorScope.GetOrCreateScopedService)).First(m => m.GetParameters().Length == 2);

                    var closedMethod = getOrCreateMethod.MakeGenericMethod(request.ActivationType);

                    createExpression = Expression.Call(request.ScopeParameter, closedMethod,
                                                       Expression.Constant(UniqueIntIdValue), Expression.Constant(CompiledDelegate));
                }
                else
                {
                    var getOrCreateMethod = typeof(IExportLocatorScope).GetRuntimeMethod(nameof(IExportLocatorScope.GetOrCreateScopedService),
                                                                                         new[] { typeof(int), typeof(ActivationStrategyDelegate), typeof(IInjectionContext) });

                    var closedMethod = getOrCreateMethod.MakeGenericMethod(request.ActivationType);

                    createExpression = Expression.Call(request.ScopeParameter, closedMethod,
                                                       Expression.Constant(UniqueIntIdValue), Expression.Constant(CompiledDelegate),
                                                       request.InjectionContextParameter);
                }
            }

            local = Expression.Variable(request.ActivationType);

            request.PerDelegateData.SetExtraData("local" + UniqueId, local);

            var assignExpression = Expression.Assign(local, createExpression);

            var result = request.Services.Compiler.CreateNewResult(request, local);

            result.AddExtraParameter(local);
            result.AddExtraExpression(assignExpression);

            return(result);
        }
예제 #16
0
        /// <inheritdoc />
        protected override IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request, ICompiledLifestyle lifestyle)
        {
            if (_proxyType == null)
            {
                lock (_proxyTypeLock)
                {
                    if (_proxyType == null)
                    {
                        var builder = new DynamicTypeBuilder();

                        _proxyType = builder.CreateType(ActivationType, out _delegateInfo);
                    }
                }
            }

            request.RequireExportScope();
            request.RequireDisposalScope();
            request.RequireInjectionContext();

            var parameters = new List <Expression>
            {
                request.ScopeParameter,
                request.DisposalScopeExpression,
                request.InjectionContextParameter
            };

            var uniqueId = UniqueStringId.Generate();

            foreach (var delegateInfo in _delegateInfo)
            {
                var locateType = delegateInfo.Method.ReturnType;

                var newRequest = request.NewRequest(locateType, this, ActivationType, RequestType.Other, null, true);

                newRequest.AddKnownValueExpression(
                    CreateKnownValueExpression(newRequest, ActivationType, uniqueId));

                if (delegateInfo.Method.Name.StartsWith("Get"))
                {
                    newRequest.SetLocateKey(delegateInfo.Method.Name.Substring("Get".Length));
                }

                if (delegateInfo.ParameterInfos != null)
                {
                    foreach (var parameter in delegateInfo.ParameterInfos)
                    {
                        newRequest.AddKnownValueExpression(
                            CreateKnownValueExpression(newRequest, parameter.ParameterInfo.ParameterType, parameter.UniqueId, parameter.ParameterInfo.Name, parameter.ParameterInfo.Position));
                    }
                }

                var result = request.Services.ExpressionBuilder.GetActivationExpression(request.RequestingScope, newRequest);

                var compiledDelegate = request.Services.Compiler.CompileDelegate(request.RequestingScope, result);

                parameters.Add(Expression.Constant(compiledDelegate));
            }

            var constructor = _proxyType.GetTypeInfo().DeclaredConstructors.First();

            request.RequireInjectionContext();

            var newStatement = Expression.New(constructor, parameters);

            var setMethod = typeof(IExtraDataContainer).GetRuntimeMethod(nameof(IExtraDataContainer.SetExtraData),
                                                                         new[] { typeof(object), typeof(object), typeof(bool) });

            var invokeStatement = Expression.Call(request.InjectionContextParameter, setMethod,
                                                  Expression.Constant(uniqueId), newStatement, Expression.Constant(true));

            var castStatement = Expression.Convert(invokeStatement, ActivationType);

            return(request.Services.Compiler.CreateNewResult(request, castStatement));
        }
예제 #17
0
        /// <summary>
        /// Get expression result from request
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="activationType"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult GetValueFromRequest(IInjectionScope scope,
                                                                          IActivationExpressionRequest request,
                                                                          Type activationType,
                                                                          object key)
        {
            var knownValues =
                request.KnownValueExpressions.Where(
                    v => activationType.GetTypeInfo().IsAssignableFrom(v.ActivationType.GetTypeInfo())).ToArray();

            if (knownValues.Length > 0)
            {
                if (knownValues.Length == 1)
                {
                    return(knownValues[0].ValueExpression(request));
                }

                if (key != null)
                {
                    IKnownValueExpression knownValue;

                    if (key is string keyString)
                    {
                        knownValue =
                            knownValues.FirstOrDefault(v =>
                                                       string.Compare(keyString, v.Key as string, StringComparison.CurrentCultureIgnoreCase) == 0);
                    }
                    else
                    {
                        knownValue = knownValues.FirstOrDefault(v => v.Key == key);
                    }

                    if (knownValue != null)
                    {
                        return(knownValue.ValueExpression(request));
                    }
                }

                if (request.Info is MemberInfo memberInfo)
                {
                    var knownValue = knownValues.FirstOrDefault(v => Equals(v.Key, memberInfo.Name));

                    if (knownValue != null)
                    {
                        return(knownValue.ValueExpression(request));
                    }
                }

                if (request.Info is ParameterInfo parameterInfo)
                {
                    var knownValue = knownValues.FirstOrDefault(v => Equals(v.Key, parameterInfo.Name));

                    if (knownValue != null)
                    {
                        return(knownValue.ValueExpression(request));
                    }

                    knownValue = knownValues.FirstOrDefault(v =>
                                                            Equals(v.Position.GetValueOrDefault(-1), parameterInfo.Position));

                    if (knownValue != null)
                    {
                        return(knownValue.ValueExpression(request));
                    }
                }

                return(knownValues[0].ValueExpression(request));
            }

            if (request.WrapperPathNode != null)
            {
                var configuration = request.WrapperPathNode.Strategy.GetActivationConfiguration(activationType);

                if (configuration.ActivationType != null &&
                    (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()) ||
                     activationType.IsConstructedGenericType && activationType.GetGenericTypeDefinition() == configuration.ActivationType))
                {
                    var wrapper = request.PopWrapperPathNode();

                    return(ProcessPathNode(scope, request, activationType, wrapper));
                }
            }
            else if (request.DecoratorPathNode != null)
            {
                var configuration = request.DecoratorPathNode.Strategy.GetActivationConfiguration(activationType);

                if (configuration.ActivationType != null &&
                    (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()) ||
                     activationType.IsConstructedGenericType && activationType.GetGenericTypeDefinition() == configuration.ActivationType))
                {
                    var decorator = request.PopDecoratorPathNode();

                    return(ProcessPathNode(scope, request, activationType, decorator));
                }
            }

            if (request.ActivationType == typeof(IInjectionScope))
            {
                if (!scope.ScopeConfiguration.Behaviors.AllowInjectionScopeLocation)
                {
                    throw new ImportInjectionScopeException(request.GetStaticInjectionContext());
                }

                request.RequireExportScope();

                var method = typeof(IExportLocatorScopeExtensions).GetRuntimeMethod(nameof(IExportLocatorScopeExtensions.GetInjectionScope), new[] { typeof(IExportLocatorScope) });

                var expression = Expression.Call(method, request.ScopeParameter);

                return(request.Services.Compiler.CreateNewResult(request, expression));
            }

            if (request.ActivationType == typeof(IExportLocatorScope) ||
                request.ActivationType == typeof(ILocatorService))
            {
                request.RequireExportScope();

                return(request.Services.Compiler.CreateNewResult(request, request.ScopeParameter));
            }

            if (request.ActivationType == typeof(IDisposalScope) ||
                (request.ActivationType == typeof(IDisposable) &&
                 request.RequestingScope.ScopeConfiguration.InjectIDisposable))
            {
                request.RequireDisposalScope();

                return(request.Services.Compiler.CreateNewResult(request, request.DisposalScopeExpression));
            }

            if (request.ActivationType == typeof(IInjectionContext))
            {
                request.RequireInjectionContext();

                return(request.Services.Compiler.CreateNewResult(request, request.InjectionContextParameter));
            }

            if (request.ActivationType == typeof(StaticInjectionContext))
            {
                var staticContext = request.Parent != null?
                                    request.Parent.GetStaticInjectionContext() :
                                        request.GetStaticInjectionContext();

                return(request.Services.Compiler.CreateNewResult(request, Expression.Constant(staticContext)));
            }

            if (request.IsDynamic)
            {
                var dynamicMethod =
                    typeof(ActivationExpressionBuilder).GetRuntimeMethod(nameof(GetDynamicValue),
                                                                         new[]
                {
                    typeof(IExportLocatorScope),
                    typeof(IDisposalScope),
                    typeof(StaticInjectionContext),
                    typeof(IInjectionContext),
                    typeof(object),
                    typeof(bool),
                    typeof(bool),
                    typeof(object)
                });

                var closedMethod = dynamicMethod.MakeGenericMethod(request.ActivationType);

                Expression defaultExpression =
                    Expression.Constant(request.DefaultValue?.DefaultValue, typeof(object));

                request.RequireExportScope();
                request.RequireDisposalScope();
                request.RequireInjectionContext();

                var expression = Expression.Call(closedMethod,
                                                 request.ScopeParameter,
                                                 request.DisposalScopeExpression,
                                                 Expression.Constant(request.GetStaticInjectionContext()),
                                                 request.InjectionContextParameter,
                                                 Expression.Constant(request.LocateKey, typeof(object)),
                                                 Expression.Constant(request.IsRequired),
                                                 Expression.Constant(request.DefaultValue != null),
                                                 defaultExpression);

                return(request.Services.Compiler.CreateNewResult(request, expression));
            }

            return(null);
        }