/// <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));
        }
        /// <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 instance = Activator.CreateInstance(closedClass, scope, request, this);

            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));
        }
示例#3
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));
        }
示例#4
0
        /// <summary>
        /// Get an activation expression for this strategy
        /// </summary>
        /// <param name="scope">IInjectionScope</param>
        /// <param name="request">IActivationExpressionRequest</param>
        /// <returns>IActivationExpressionResult</returns>
        public override IActivationExpressionResult GetActivationExpression(
            IInjectionScope scope,
            IActivationExpressionRequest request)
        {
            var activationDelegate = CompileDelegate(scope, request);

            var factory = typeof(GraceOptionalFactory <>)
                          .MakeGenericType(request.ActivationType.GenericTypeArguments[0])
                          .GetConstructors()
                          .First()
                          .Invoke(new object[] { activationDelegate, request.LocateKey });

            var callExpression = Expression.Call(
                Expression.Constant(factory),
                factory.GetType().GetMethod(nameof(GraceOptionalFactory <object> .CreateOptional)),
                request.ScopeParameter,
                request.DisposalScopeExpression,
                request.InjectionContextParameter);

            request.RequireInjectionContext();

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
        public IActivationExpressionResult ProvideLifestyleExpression(IInjectionScope scope, IActivationExpressionRequest request,
                                                                      Func <IActivationExpressionRequest, IActivationExpressionResult> activationExpression)
        {
            request.RequireInjectionContext();

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

            // Create new request as we shouldn't carry over anything from the previous request
            var newRequest = request.NewRootedRequest(request.ActivationType, scope, true);

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

            ConstantExpression = Expression.Convert(Expression.Call(Expression.Constant(this), getInstanceMethodInfo,
                                                                    newRequest.ScopeParameter, Expression.Constant(scope), request.InjectionContextParameter,
                                                                    Expression.Constant(_activationDelegate)), request.ActivationType);

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

            return(result);
        }
示例#6
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));
        }
        /// <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);
        }
示例#8
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);
        }