/// <summary>
        /// Creates decorated expression for activation strategy
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="strategy"></param>
        /// <param name="decorators"></param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult CreateDecoratedActivationStrategy(IInjectionScope scope, IActivationExpressionRequest request, ICompiledExportStrategy strategy, List <ICompiledDecoratorStrategy> decorators)
        {
            decorators.Sort((x, y) => Comparer <int> .Default.Compare(x.Priority, y.Priority));

            var pathNodes = ImmutableLinkedList <IActivationPathNode> .Empty;

            if (decorators.All(d => d.ApplyAfterLifestyle))
            {
                pathNodes = pathNodes.Add(new DecoratorActivationPathNode(strategy, request.ActivationType, strategy.Lifestyle));

                foreach (var decorator in decorators)
                {
                    pathNodes = pathNodes.Add(new DecoratorActivationPathNode(decorator, request.ActivationType, null));
                }
            }
            else
            {
                pathNodes = pathNodes.Add(new DecoratorActivationPathNode(strategy, request.ActivationType, null));

                DecoratorActivationPathNode currentNode = null;

                foreach (var decorator in decorators.Where(d => !d.ApplyAfterLifestyle))
                {
                    currentNode = new DecoratorActivationPathNode(decorator, request.ActivationType, null);

                    pathNodes = pathNodes.Add(currentNode);
                }

                if (currentNode != null)
                {
                    currentNode.Lifestyle = strategy.Lifestyle;
                }

                foreach (var decorator in decorators.Where(d => d.ApplyAfterLifestyle))
                {
                    pathNodes = pathNodes.Add(new DecoratorActivationPathNode(decorator, request.ActivationType, null));
                }
            }

            request.SetDecoratorPath(pathNodes);

            var pathNode = request.PopDecoratorPathNode();

            return(pathNode.GetActivationExpression(scope, request));
        }
Example #2
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);
        }
Example #3
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);
        }
        /// <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);
        }