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

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

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

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

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

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

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

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

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

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

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #3
0
        /// <summary>
        /// Create expression to add instance to disposal scope
        /// </summary>
        /// <param name="scope">scope for strategy</param>
        /// <param name="request">request</param>
        /// <param name="activationConfiguration">activation configuration</param>
        /// <param name="result">result for instantiation</param>
        /// <returns></returns>
        public IActivationExpressionResult CreateExpression(IInjectionScope scope, IActivationExpressionRequest request, TypeActivationConfiguration activationConfiguration, IActivationExpressionResult result)
        {
            var closedActionType = typeof(Action <>).MakeGenericType(activationConfiguration.ActivationType);

            object disposalDelegate = null;

            if (closedActionType == activationConfiguration.DisposalDelegate?.GetType())
            {
                disposalDelegate = activationConfiguration.DisposalDelegate;
            }

            MethodInfo closedGeneric;

            Expression[] parameterExpressions;

            var resultExpression = result.Expression;

            if (resultExpression.Type != activationConfiguration.ActivationType)
            {
                resultExpression = Expression.Convert(resultExpression, activationConfiguration.ActivationType);
            }

            if (disposalDelegate != null)
            {
                closedGeneric        = AddMethodWithCleanup.MakeGenericMethod(activationConfiguration.ActivationType);
                parameterExpressions = new[] { resultExpression, Expression.Convert(Expression.Constant(disposalDelegate), closedActionType) };
            }
            else
            {
                closedGeneric        = AddMethod.MakeGenericMethod(activationConfiguration.ActivationType);
                parameterExpressions = new[] { resultExpression };
            }

            request.RequireDisposalScope();

            var disposalCall = Expression.Call(request.DisposalScopeExpression, closedGeneric, parameterExpressions);

            var disposalResult = request.Services.Compiler.CreateNewResult(request, disposalCall);

            disposalResult.AddExpressionResult(result);

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

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

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

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

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

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

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

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

            return(request.Services.Compiler.CreateNewResult(request, callExpression));
        }
예제 #5
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));
        }
예제 #6
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>
        /// <param name="allowNull"></param>
        /// <returns></returns>
        public static Expression ApplyNullCheckAndAddDisposal(IInjectionScope scope,
                                                              IActivationExpressionRequest request, Expression expression, bool allowDisposableTracking, bool allowNull)
        {
            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 == nameof(ValueOrDefault));

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

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

                if (!allowNull &&
                    !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)
            {
                request.RequireDisposalScope();

                var method = typeof(ExpressionUtilities).GetRuntimeMethods()
                             .FirstOrDefault(m => m.Name == nameof(AddToDisposableScopeOrDefault));

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

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

            if (allowNull ||
                scope.ScopeConfiguration.Behaviors.AllowInstanceAndFactoryToReturnNull ||
                !request.IsRequired)
            {
                request.RequireDisposalScope();

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

                return(Expression.Call(closedMethod, request.DisposalScopeExpression, expression));
            }
            else
            {
                request.RequireDisposalScope();

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

                return(Expression.Call(closedMethod,
                                       request.DisposalScopeExpression,
                                       Expression.Constant(request.GetStaticInjectionContext()), expression));
            }
        }
예제 #7
0
        /// <summary>
        /// Get expression result from request
        /// </summary>
        /// <param name="scope"></param>
        /// <param name="request"></param>
        /// <param name="activationType"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        protected virtual IActivationExpressionResult GetValueFromRequest(IInjectionScope scope,
                                                                          IActivationExpressionRequest request,
                                                                          Type activationType,
                                                                          object key)
        {
            var knownValues =
                request.KnownValueExpressions.Where(
                    v => activationType.GetTypeInfo().IsAssignableFrom(v.ActivationType.GetTypeInfo())).ToArray();

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

                if (key != null)
                {
                    IKnownValueExpression knownValue;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                request.RequireExportScope();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            return(null);
        }