/// <summary>
        /// Find decorators for a given type
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="type"></param>
        /// <param name="strategy"></param>
        /// <returns></returns>
        protected virtual List <ICompiledDecoratorStrategy> FindDecoratorsForType(IInjectionScope scope, IActivationExpressionRequest request, Type type, ICompiledExportStrategy strategy)
        {
            List <ICompiledDecoratorStrategy> decorators             = new List <ICompiledDecoratorStrategy>();
            StaticInjectionContext            staticInjectionContext = null;
            var collection =
                scope.DecoratorCollectionContainer.GetActivationStrategyCollection(type);

            if (collection != null)
            {
                foreach (var decorator in collection.GetStrategies())
                {
                    if (decorator.HasConditions)
                    {
                        if (staticInjectionContext == null)
                        {
                            staticInjectionContext = request.GetStaticInjectionContext();
                        }

                        if (!decorator.Conditions.All(
                                condition => condition.MeetsCondition(strategy, staticInjectionContext)))
                        {
                            continue;
                        }
                    }

                    decorators.Add(decorator);
                }
            }

            if (type.IsConstructedGenericType)
            {
                var generic = type.GetGenericTypeDefinition();

                collection = scope.DecoratorCollectionContainer.GetActivationStrategyCollection(generic);

                if (collection != null)
                {
                    foreach (var decorator in collection.GetStrategies())
                    {
                        if (decorator.HasConditions)
                        {
                            if (staticInjectionContext == null)
                            {
                                staticInjectionContext = request.GetStaticInjectionContext();
                            }

                            if (!decorator.Conditions.All(
                                    condition => condition.MeetsCondition(strategy, staticInjectionContext)))
                            {
                                continue;
                            }
                        }

                        decorators.Add(decorator);
                    }
                }
            }

            return(decorators);
        }
        /// <summary>
        /// Applies null check and disposal scope tracking logic to an expression
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="expression"></param>
        /// <param name="allowDisposableTracking"></param>
        /// <returns></returns>
        public static Expression ApplyNullCheckAndAddDisposal(IInjectionScope scope, IActivationExpressionRequest request, Expression expression, bool allowDisposableTracking)
        {
            if (expression.Type != request.ActivationType &&
                !ReflectionService.CheckTypeIsBasedOnAnotherType(expression.Type, request.ActivationType))
            {
                expression = Expression.Convert(expression, request.ActivationType);
            }

            if (!allowDisposableTracking)
            {
                if (request.DefaultValue != null)
                {
                    var method = typeof(ExpressionUtilities).GetRuntimeMethods()
                                 .FirstOrDefault(m => m.Name == "ValueOrDefault");

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

                    return(Expression.Call(closedMethod, expression, Expression.Constant(request.DefaultValue.DefaultValue, request.ActivationType)));
                }

                if (!scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull &&
                    request.IsRequired)
                {
                    var closedMethod = CheckForNullMethodInfo.MakeGenericMethod(request.ActivationType);

                    return(Expression.Call(closedMethod,
                                           Expression.Constant(request.GetStaticInjectionContext()),
                                           expression));
                }

                return(expression);
            }
            if (request.DefaultValue != null)
            {
                var method = typeof(ExpressionUtilities).GetRuntimeMethods()
                             .FirstOrDefault(m => m.Name == "AddToDisposableScopeOrDefault");

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

                return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression, Expression.Constant(request.DefaultValue.DefaultValue, request.ActivationType)));
            }

            if (scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull ||
                !request.IsRequired)
            {
                var closedMethod = AddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType);

                return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression));
            }
            else
            {
                var closedMethod = CheckForNullAndAddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType);

                return(Expression.Call(closedMethod,
                                       request.DisposalScopeExpression,
                                       Expression.Constant(request.GetStaticInjectionContext()), expression));
            }
        }
        private IActivationExpressionResult GetExpressionFromDependentStrategy(IInjectionScope scope,
                                                                               IActivationExpressionRequest request)
        {
            var newRequest = request.NewRequest(_dependentStrategy.ActivationType, this, request.InjectedType,
                                                request.RequestType, request.Info, true, true);

            var instanceResult = _dependentStrategy.GetActivationExpression(scope, newRequest);

            Expression propertyExpression;

            try
            {
                propertyExpression = Expression.PropertyOrField(instanceResult.Expression, _propertyOrFieldName);
            }
            catch (Exception exp)
            {
                throw new LocateException(request.GetStaticInjectionContext(), exp, $"Could not create property/field expression for {_propertyOrFieldName} on type {instanceResult.Expression.Type.FullName}");
            }

            var expressionResult = request.Services.Compiler.CreateNewResult(request, propertyExpression);

            expressionResult.AddExpressionResult(instanceResult);

            return(expressionResult);
        }
        /// <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("GetValueFromScope",
                                                                         new[]
            {
                typeof(IExportLocatorScope),
                typeof(ActivationStrategyDelegate),
                typeof(string),
                typeof(string),
                typeof(StaticInjectionContext)
            });

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

            var expression = Expression.Call(closedMethod,
                                             request.Constants.ScopeParameter,
                                             Expression.Constant(CompiledDelegate),
                                             Expression.Constant(UniqueId),
                                             Expression.Constant(_scopeName),
                                             Expression.Constant(request.GetStaticInjectionContext()));

            return(request.Services.Compiler.CreateNewResult(request, expression));
        }
Exemple #5
0
            /// <summary>
            /// Provide linq expression for the missing dependency
            /// </summary>
            /// <param name="scope"></param>
            /// <param name="request"></param>
            /// <returns>return expression or null if it's not possible</returns>
            public IActivationExpressionResult ProvideExpression(IInjectionScope scope, IActivationExpressionRequest request)
            {
                var valueProvider =
                    scope.ScopeConfiguration.Implementation.Locate <IInjectionContextValueProvider>();

                var key = request.LocateKey;

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

                var locateFromChildMethod = GetType().GetTypeInfo().GetDeclaredMethod("LocateFromChildContainer");

                Expression expression = Expression.Call(Expression.Constant(this),
                                                        locateFromChildMethod,
                                                        Expression.Constant(valueProvider),
                                                        request.ScopeParameter,
                                                        Expression.Constant(request.GetStaticInjectionContext()),
                                                        Expression.Constant(request.ActivationType),
                                                        Expression.Constant(key),
                                                        request.Constants.InjectionContextParameter,
                                                        Expression.Constant(request.DefaultValue?.DefaultValue),
                                                        Expression.Constant(request.DefaultValue != null),
                                                        Expression.Constant(request.IsRequired));

                expression = Expression.Convert(expression, request.ActivationType);

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

                result.UsingFallbackExpression = true;

                return(result);
            }
        /// <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("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);

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

            request.RequireInjectionContext();

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
Exemple #7
0
        private IActivationExpressionResult CreateTimedCreateExpression(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration, IActivationExpressionResult expression)
        {
            var result = request.Services.Compiler.CreateNewResult(request);

            var returnVar     = Expression.Variable(typeof(object));
            var staticContext = request.GetStaticInjectionContext();

            var callExpression = Expression.Call(Expression.Constant(this),
                                                 PreBuildUpMethodInfo,
                                                 Expression.Constant(staticContext),
                                                 request.Constants.ScopeParameter,
                                                 request.InjectionContextParameter);

            result.AddExtraParameter(returnVar);
            result.AddExtraExpression(Expression.Assign(returnVar, callExpression));

            result.AddExtraExpression(
                Expression.IfThen(Expression.Equal(returnVar,
                                                   Expression.Constant(null, typeof(object))),
                                  Expression.Assign(returnVar, expression.Expression)));

            result.Expression = Expression.Call(Expression.Constant(this),
                                                PostBuildUpMethodInfo,
                                                returnVar,
                                                Expression.Constant(staticContext),
                                                request.ScopeParameter,
                                                request.InjectionContextParameter);

            return(result);
        }
        /// <summary>
        /// Select the best strategy from collection to satisfy request
        /// </summary>
        /// <param name="collection"></param>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult SelectStrategyFromCollection(IActivationStrategyCollection <ICompiledExportStrategy> collection, IInjectionScope scope, IActivationExpressionRequest request)
        {
            var filter = request.Filter;
            IActivationExpressionResult result = null;

            foreach (var strategy in collection.GetStrategies())
            {
                if (filter != null && !filter(strategy))
                {
                    continue;
                }

                if (strategy.HasConditions)
                {
                    var context = request.GetStaticInjectionContext();

                    if (!strategy.Conditions.All(condition => condition.MeetsCondition(strategy, context)))
                    {
                        continue;
                    }
                }

                result = strategy.GetActivationExpression(scope, request);

                if (result != null)
                {
                    break;
                }
            }

            return(result);
        }
        /// <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 = typeof(ActivationExpressionBuilder).GetRuntimeMethod("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();
            }

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

            return(request.Services.Compiler.CreateNewResult(request, expresion));
        }
Exemple #10
0
        /// <summary>
        /// Get wrappers for a request
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="type"></param>
        /// <param name="request"></param>
        /// <param name="wrappedType"></param>
        /// <returns></returns>
        public ImmutableLinkedList <IActivationPathNode> GetWrappers(IInjectionScope scope, Type type, IActivationExpressionRequest request, out Type wrappedType)
        {
            var wrapperCollection = scope.WrapperCollectionContainer.GetActivationStrategyCollection(type);

            if (wrapperCollection == null && type.IsConstructedGenericType)
            {
                var genericType = type.GetGenericTypeDefinition();

                wrapperCollection = scope.WrapperCollectionContainer.GetActivationStrategyCollection(genericType);
            }

            if (wrapperCollection != null)
            {
                var strategy = request.Filter == null?wrapperCollection.GetPrimary() : null;

                if (strategy == null)
                {
                    foreach (var s in wrapperCollection.GetStrategies())
                    {
                        var pass = true;
                        if (s.HasConditions)
                        {
                            foreach (var condition in s.Conditions)
                            {
                                if (!condition.MeetsCondition(s, request.GetStaticInjectionContext()))
                                {
                                    pass = false;
                                }
                            }
                        }

                        if (pass)
                        {
                            strategy = s;
                            break;
                        }
                    }
                }

                if (strategy != null)
                {
                    var newType = strategy.GetWrappedType(type);

                    if (newType == null)
                    {
                        throw new Exception("Wrapper strategy returned null for wrapped type, " +
                                            strategy.GetType().FullName);
                    }

                    return(GetWrappers(scope, newType, request, out wrappedType).Add(new WrapperActivationPathNode(strategy, type, null)));
                }
            }

            wrappedType = type;

            return(ImmutableLinkedList <IActivationPathNode> .Empty);
        }
Exemple #11
0
        /// <summary>
        /// Applies null check and disposal scope tracking logic to an expression
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="expression"></param>
        /// <param name="allowDisposableTracking"></param>
        /// <returns></returns>
        public static Expression ApplyNullCheckAndAddDisposal(IInjectionScope scope, IActivationExpressionRequest request, Expression expression, bool allowDisposableTracking)
        {
            if (expression.Type != request.ActivationType &&
                !ReflectionService.CheckTypeIsBasedOnAnotherType(expression.Type, request.ActivationType))
            {
                expression = Expression.Convert(expression, request.ActivationType);
            }

            if (!allowDisposableTracking)
            {
                if (!scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull)
                {
                    var closedMethod = CheckForNullMethodInfo.MakeGenericMethod(request.ActivationType);

                    return(Expression.Call(closedMethod,
                                           Expression.Constant(request.GetStaticInjectionContext()),
                                           expression));
                }
            }
            else
            {
                if (scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull)
                {
                    var closedMethod = AddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType);

                    return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression));
                }
                else
                {
                    var closedMethod =
                        CheckForNullAndAddToDisposalScopeMethodInfo.MakeGenericMethod(request.ActivationType);

                    return(Expression.Call(closedMethod,
                                           request.DisposalScopeExpression,
                                           Expression.Constant(request.GetStaticInjectionContext()), expression));
                }
            }

            return(expression);
        }
Exemple #12
0
        private IActivationExpressionResult CreateExpressionResultFromBindingAttribute(IInjectionScope scope,
                                                                                       IActivationExpressionRequest request,
                                                                                       object cacheKey,
                                                                                       string name,
                                                                                       Type modelType,
                                                                                       IEnumerable <object> attributes)
        {
            var closedType = typeof(BindingSourceHelper <>).MakeGenericType(modelType);


            if (_modelBinderFactory == null)
            {
                scope.TryLocate(out _modelBinderFactory);
            }

            if (_modelMetadataProvider == null)
            {
                scope.TryLocate(out _modelMetadataProvider);
            }

            if (_factories == null)
            {
                if (scope.TryLocate(out IOptions <MvcOptions> optionsAccessor))
                {
                    _factories = optionsAccessor.Value.ValueProviderFactories.ToArray();
                }
            }

            if (_modelBinderFactory != null && _modelMetadataProvider != null && _factories != null)
            {
                var defaultValue = request.DefaultValue?.DefaultValue;

                var instance = Activator.CreateInstance(closedType,
                                                        _factories,
                                                        name,
                                                        attributes,
                                                        defaultValue,
                                                        request.GetStaticInjectionContext());

                var closedMethod = closedType.GetRuntimeMethod("GetValue", new[] { typeof(IExportLocatorScope) });

                var expression = Expression.Call(Expression.Constant(instance),
                                                 closedMethod,
                                                 request.Constants.ScopeParameter);

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

            return(null);
        }
Exemple #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)
        {
            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));
        }
        /// <summary>
        /// Get expression from an activation strategy collection
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="arrayElementType"></param>
        /// <param name="request"></param>
        /// <param name="expressions"></param>
        /// <param name="collection"></param>
        /// <param name="wrappedType"></param>
        /// <param name="wrappers"></param>
        public static void GetExpressionFromCollection(IInjectionScope scope, Type arrayElementType,
                                                       IActivationExpressionRequest request, List <IActivationExpressionResult> expressions, IActivationStrategyCollection <ICompiledExportStrategy> collection, Type wrappedType,
                                                       ImmutableLinkedList <IActivationPathNode> wrappers)
        {
            foreach (var strategy in collection.GetStrategies())
            {
                if (strategy.HasConditions)
                {
                    var staticContext = request.GetStaticInjectionContext();
                    var pass          = true;

                    foreach (var condition in strategy.Conditions)
                    {
                        if (!condition.MeetsCondition(strategy, staticContext))
                        {
                            pass = false;
                            break;
                        }
                    }

                    if (!pass)
                    {
                        continue;
                    }
                }

                var newRequest = request.NewRequest(arrayElementType, request.RequestingStrategy, request.RequestingStrategy?.ActivationType,
                                                    RequestType.Other, null, true);

                var newPath =
                    ImmutableLinkedList <IActivationPathNode> .Empty.Add(
                        new WrapperActivationPathNode(strategy,
                                                      wrappedType, null)).AddRange(wrappers);

                newRequest.SetWrapperPath(newPath);

                var wrapper = newRequest.PopWrapperPathNode();

                expressions.Add(wrapper.GetActivationExpression(scope, newRequest));
            }
        }
        /// <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);
        }
Exemple #16
0
        /// <summary>
        /// Creates member injection statements
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="activationConfiguration"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult CreateMemberInjectExpressions(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration, IActivationExpressionResult result)
        {
            var members = GetMemberInjectionInfoForConfiguration(scope, request, activationConfiguration);

            if (members.Count == 0)
            {
                return(result);
            }

            ParameterExpression variable = result.Expression as ParameterExpression;

            var newResult = request.Services.Compiler.CreateNewResult(request);

            if (variable == null)
            {
                variable = Expression.Variable(result.Expression.Type);

                newResult.AddExpressionResult(result);

                newResult.AddExtraParameter(variable);
                newResult.AddExtraExpression(Expression.Assign(variable, result.Expression));
            }

            foreach (var memberKVP in members)
            {
                var expression = memberKVP.Value.CreateExpression;

                if (expression == null)
                {
                    var memberType = memberKVP.Key.GetMemeberType();

                    var newRequest =
                        request.NewRequest(memberType, activationConfiguration.ActivationStrategy,
                                           activationConfiguration.ActivationType, RequestType.Member, memberKVP.Key, false, true);

                    if (memberKVP.Value.LocateKey == null &&
                        scope.ScopeConfiguration.Behaviors.KeyedTypeSelector(memberType))
                    {
                        newRequest.SetLocateKey(memberKVP.Key.Name);
                    }
                    else
                    {
                        newRequest.SetLocateKey(memberKVP.Value.LocateKey);
                    }

                    newRequest.IsDynamic = memberKVP.Value.IsDynamic;
                    newRequest.SetIsRequired(memberKVP.Value.IsRequired);
                    newRequest.SetFilter(memberKVP.Value.Filter);

                    if (memberKVP.Value.DefaultValue != null)
                    {
                        newRequest.SetDefaultValue(
                            new DefaultValueInformation {
                            DefaultValue = memberKVP.Value.DefaultValue
                        });
                    }

                    var memberResult = request.Services.ExpressionBuilder.GetActivationExpression(scope, newRequest);

                    if (memberResult == null)
                    {
                        if (memberKVP.Value.IsRequired)
                        {
                            throw new LocateException(newRequest.GetStaticInjectionContext());
                        }
                    }
                    else
                    {
                        Expression memberExpression;

                        if (memberKVP.Key is FieldInfo)
                        {
                            memberExpression = Expression.Field(variable, memberKVP.Key as FieldInfo);
                        }
                        else if (memberKVP.Key is PropertyInfo)
                        {
                            memberExpression = Expression.Property(variable, (PropertyInfo)memberKVP.Key);
                        }
                        else
                        {
                            throw new LocateException(request.GetStaticInjectionContext(), $"{memberKVP.Key.GetType().Name} member type not supported");
                        }

                        newResult.AddExpressionResult(memberResult);

                        newResult.AddExtraExpression(Expression.Assign(memberExpression, memberResult.Expression));
                    }
                }
                else
                {
                    Expression memberExpression;

                    if (memberKVP.Key is FieldInfo)
                    {
                        memberExpression = Expression.Field(variable, memberKVP.Key as FieldInfo);
                    }
                    else if (memberKVP.Key is PropertyInfo)
                    {
                        memberExpression = Expression.Property(variable, (PropertyInfo)memberKVP.Key);
                    }
                    else
                    {
                        throw new LocateException(request.GetStaticInjectionContext(), $"{memberKVP.Key.GetType().Name} member type not supported");
                    }

                    newResult.AddExtraExpression(Expression.Assign(memberExpression, expression));
                }
            }

            newResult.Expression = variable;

            return(newResult);
        }
Exemple #17
0
        private IActivationExpressionResult BuildActivationExpression(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration)
        {
            var returnLabel             = Expression.Label(typeof(object));
            var variables               = new List <ParameterExpression>();
            var testVariableExpressions = new List <Expression>();
            var testExpressions         = new List <Expression>();

            var foundValues = new Dictionary <string, Tuple <ParameterExpression, string> >();
            var throwAtEnd  = true;

            foreach (var constructorInfo in GetConstructors(activationConfiguration.ActivationType))
            {
                var testParameters   = new List <ParameterExpression>();
                var locateParameters = new List <Expression>();

                foreach (var parameter in constructorInfo.GetParameters())
                {
                    var paramKey = parameter.Name + "|" + parameter.ParameterType.FullName;

                    Tuple <ParameterExpression, string> parameterExpression;

                    if (!foundValues.TryGetValue(paramKey, out parameterExpression))
                    {
                        var canLocateInfo = CreateCanLocateStatement(parameter, scope, request, activationConfiguration);

                        // only test for required parameters with no default value
                        if (canLocateInfo != null)
                        {
                            parameterExpression = new Tuple <ParameterExpression, string>(canLocateInfo.Item1, $"{parameter.ParameterType.Name} {parameter.Name}");

                            foundValues.Add(paramKey, parameterExpression);
                            variables.Add(parameterExpression.Item1);
                            testVariableExpressions.Add(canLocateInfo.Item2);
                        }
                    }

                    if (parameterExpression != null)
                    {
                        testParameters.Add(parameterExpression.Item1);
                    }

                    locateParameters.Add(CreateLocateExpression(parameter, scope, request, activationConfiguration));
                }

                var newValue = Expression.Return(returnLabel, Expression.New(constructorInfo, locateParameters));

                if (testParameters.Count > 0)
                {
                    if (testParameters.Count == 1)
                    {
                        testExpressions.Add(Expression.IfThen(Expression.IsTrue(testParameters[0]), newValue));
                    }
                    else
                    {
                        var andExpression = Expression.And(testParameters[0], testParameters[1]);

                        for (int i = 2; i < testParameters.Count; i++)
                        {
                            andExpression = Expression.And(andExpression, testParameters[i]);
                        }

                        testExpressions.Add(Expression.IfThen(andExpression, newValue));
                    }
                }
                else
                {
                    testExpressions.Add(newValue);
                    throwAtEnd = false;
                    break;
                }
            }

            if (throwAtEnd)
            {
                var constructor = typeof(LocateException).GetTypeInfo()
                                  .DeclaredConstructors.Single(c => c.GetParameters().Length == 2);

                var testValues = foundValues.Values.ToArray();

                var foundArrayExpression = Expression.NewArrayInit(typeof(bool), testValues.Select(t => t.Item1));
                var labelArray           = Expression.Constant(testValues.Select(t => t.Item2).ToArray());

                var createErrorStringMethod = typeof(DynamicConstructorExpressionCreator).GetTypeInfo()
                                              .GetDeclaredMethod("CreateMissingErrorMessage");

                testExpressions.Add(Expression.Throw(Expression.New(constructor,
                                                                    Expression.Constant(request.GetStaticInjectionContext()),
                                                                    Expression.Call(createErrorStringMethod, foundArrayExpression, labelArray))));
            }

            var result =
                request.Services.Compiler.CreateNewResult(request, Expression.Label(returnLabel, Expression.Default(request.ActivationType)));

            foreach (var variable in variables)
            {
                result.AddExtraParameter(variable);
            }

            foreach (var expression in testVariableExpressions)
            {
                result.AddExtraExpression(expression);
            }

            foreach (var expression in testExpressions)
            {
                result.AddExtraExpression(expression);
            }

            return(result);
        }
Exemple #18
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 (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()))
                {
                    var wrapper = request.PopWrapperPathNode();

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

                if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()))
                {
                    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());
                }

                var method = typeof(IExportLocatorScopeExtensions).GetRuntimeMethod("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))
            {
                return(request.Services.Compiler.CreateNewResult(request, request.ScopeParameter));
            }

            if (request.ActivationType == typeof(IDisposalScope) ||
                (request.ActivationType == typeof(IDisposable) &&
                 request.RequestingScope.ScopeConfiguration.InjectIDisposable))
            {
                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("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));

                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);
        }
Exemple #19
0
        /// <summary>
        /// Sets up wrappers for request
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool SetupWrappersForRequest(IInjectionScope scope, IActivationExpressionRequest request)
        {
            Type wrappedType;

            var wrappers = GetWrappers(scope, request.ActivationType, request, out wrappedType);

            if (wrappers != ImmutableLinkedList <IActivationPathNode> .Empty)
            {
                if (request.DecoratorPathNode != null &&
                    wrappedType.GetTypeInfo().IsAssignableFrom(request.DecoratorPathNode.Strategy.ActivationType.GetTypeInfo()))
                {
                    var decorator = request.PopDecoratorPathNode();

                    wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(decorator).AddRange(wrappers.Reverse());
                }
                else
                {
                    var collection = GetWrappedTypeFromStrategiesCollection(scope, wrappedType);

                    if (collection == null)
                    {
                        lock (scope.GetLockObject(InjectionScope.ActivationStrategyAddLockName))
                        {
                            var newRequest = request.NewRequest(wrappedType, request.RequestingStrategy,
                                                                request.InjectedType, request.RequestType, request.Info, false, true);

                            request.Services.Compiler.ProcessMissingStrategyProviders(scope, newRequest);
                        }

                        collection = GetWrappedTypeFromStrategiesCollection(scope, wrappedType);
                    }

                    if (collection != null)
                    {
                        if (request.LocateKey != null)
                        {
                            var strategy = collection.GetKeyedStrategy(request.LocateKey);

                            if (strategy != null)
                            {
                                wrappers = ImmutableLinkedList <IActivationPathNode> .Empty
                                           .Add(new WrapperActivationPathNode(strategy, wrappedType, null))
                                           .AddRange(wrappers.Reverse());
                            }
                        }
                        else
                        {
                            var primary = request.Filter == null?collection.GetPrimary() : null;

                            if (primary != null && primary != request.RequestingStrategy)
                            {
                                wrappers = ImmutableLinkedList <IActivationPathNode> .Empty
                                           .Add(new WrapperActivationPathNode(primary, wrappedType, null))
                                           .AddRange(wrappers.Reverse());
                            }
                            else
                            {
                                foreach (var strategy in collection.GetStrategies())
                                {
                                    var pass = true;

                                    if (strategy.HasConditions)
                                    {
                                        foreach (var condition in strategy.Conditions)
                                        {
                                            if (!condition.MeetsCondition(strategy,
                                                                          request.GetStaticInjectionContext()))
                                            {
                                                pass = false;
                                                break;
                                            }
                                        }
                                    }

                                    if (pass &&
                                        request.RequestingStrategy != strategy &&
                                        (request.Filter == null || request.Filter(strategy)))
                                    {
                                        wrappers = ImmutableLinkedList <IActivationPathNode> .Empty
                                                   .Add(new WrapperActivationPathNode(strategy, wrappedType, null))
                                                   .AddRange(wrappers.Reverse());
                                    }
                                }
                            }
                        }
                    }
                    else if (!wrappedType.IsArray &&
                             (!wrappedType.IsConstructedGenericType || wrappedType.GetGenericTypeDefinition() != typeof(IEnumerable <>)))
                    {
                        return(false);
                    }
                }

                request.SetWrapperPath(wrappers);

                return(true);
            }

            return(false);
        }
        /// <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 knownValue =
                request.KnownValueExpressions.FirstOrDefault(
                    v => activationType.GetTypeInfo().IsAssignableFrom(v.ActivationType.GetTypeInfo()));

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

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

                if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()))
                {
                    var wrapper = request.PopWrapperPathNode();

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

                if (activationType.GetTypeInfo().IsAssignableFrom(configuration.ActivationType.GetTypeInfo()))
                {
                    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());
                }

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

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

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

            if (request.ActivationType == typeof(IExportLocatorScope) ||
                request.ActivationType == typeof(ILocatorService))
            {
                return(request.Services.Compiler.CreateNewResult(request, request.Constants.ScopeParameter));
            }

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

                return(request.Services.Compiler.CreateNewResult(request, request.Constants.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("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));

                var expression = Expression.Call(closedMethod,
                                                 request.Constants.ScopeParameter,
                                                 request.DisposalScopeExpression,
                                                 Expression.Constant(request.GetStaticInjectionContext()),
                                                 request.Constants.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);
        }
        /// <summary>
        /// Get an activation expression for a request
        /// </summary>
        /// <param name="scope">scope for request</param>
        /// <param name="request">request</param>
        /// <returns></returns>
        public IActivationExpressionResult GetActivationExpression(IInjectionScope scope, IActivationExpressionRequest request)
        {
            Type wrappedType;

            var wrappers = GetWrappers(scope, request.ActivationType, request, out wrappedType);

            if (wrappers != ImmutableLinkedList <IActivationPathNode> .Empty)
            {
                if (request.DecoratorPathNode != null &&
                    wrappedType.GetTypeInfo().IsAssignableFrom(request.DecoratorPathNode.Strategy.ActivationType.GetTypeInfo()))
                {
                    var decorator = request.PopDecoratorPathNode();

                    wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(decorator).AddRange(wrappers.Reverse());
                }
                else
                {
                    var collection = scope.StrategyCollectionContainer.GetActivationStrategyCollection(wrappedType);

                    if (collection == null && wrappedType.IsConstructedGenericType)
                    {
                        var generic = wrappedType.GetGenericTypeDefinition();

                        collection = scope.StrategyCollectionContainer.GetActivationStrategyCollection(generic);
                    }

                    if (collection != null)
                    {
                        var primary = request.Filter == null?collection.GetPrimary() : null;

                        if (primary != null)
                        {
                            wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(new WrapperActivationPathNode(primary, wrappedType, null)).AddRange(wrappers.Reverse());
                        }
                        else
                        {
                            foreach (var strategy in collection.GetStrategies())
                            {
                                var pass = true;

                                if (strategy.HasConditions)
                                {
                                    foreach (var condition in strategy.Conditions)
                                    {
                                        if (!condition.MeetsCondition(strategy, request.GetStaticInjectionContext()))
                                        {
                                            pass = false;
                                            break;
                                        }
                                    }
                                }

                                if (pass &&
                                    (request.Filter == null || request.Filter(strategy)))
                                {
                                    wrappers = ImmutableLinkedList <IActivationPathNode> .Empty.Add(new WrapperActivationPathNode(strategy, wrappedType, null)).AddRange(wrappers.Reverse());
                                }
                            }
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }

                request.SetWrapperPath(wrappers);

                var wrapper = request.PopWrapperPathNode();

                return(wrapper.GetActivationExpression(scope, request));
            }

            return(null);
        }