Exemple #1
0
        private bool ProcessConstantFromArrayTarget(DynamicMethodGenerationRequest request, ConstantExpression expression)
        {
            var constantIndex = request.Constants.IndexOf(expression.Value);

            if (constantIndex < 0)
            {
                return(false);
            }

            var field = request.Target.GetType().GetRuntimeField("Items");

            request.ILGenerator.Emit(OpCodes.Ldarg_0);

            request.ILGenerator.Emit(OpCodes.Ldfld, field);

            request.ILGenerator.EmitInt(constantIndex);

            request.ILGenerator.Emit(OpCodes.Ldelem_Ref);

            if (expression.Type != typeof(object))
            {
                request.ILGenerator.Emit(OpCodes.Castclass, expression.Type);
            }

            return(true);
        }
        /// <summary>
        /// Generate IL for ParameterExpression
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, ParameterExpression expression)
        {
            var expressionConstants = request.ExpressionRequest.Constants;

            if (expression == expressionConstants.ScopeParameter)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_1);

                return(true);
            }

            if (expression == expressionConstants.RootDisposalScope)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_2);

                return(true);
            }

            if (expression == expressionConstants.InjectionContextParameter)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_3);

                return(true);
            }

            return(false);
        }
        /// <summary>
        /// try to create delegate using IL generation
        /// </summary>
        /// <param name="expressionContext">expression context</param>
        /// <param name="finalExpression">final expression to convert</param>
        /// <param name="newDelegate">created delegate</param>
        /// <returns>true if delegate was created</returns>
        public virtual bool TryCreateDelegate(IActivationExpressionResult expressionContext, Expression finalExpression,
                                              out ActivationStrategyDelegate newDelegate)
        {
            newDelegate = null;

            try
            {
                var request = new DynamicMethodGenerationRequest(expressionContext, TryGenerateIL);

                var constants = new List <object>();

                if (!ImplementationFactory.Locate <IConstantExpressionCollector>().GetConstantExpressions(finalExpression, constants))
                {
                    return(false);
                }

                request.Constants = constants;

                var target = ImplementationFactory.Locate <IDynamicMethodTargetCreator>().CreateMethodTarget(request);

                if (target == null)
                {
                    return(false);
                }

                request.Target = target;

                var method = new DynamicMethod(string.Empty,
                                               typeof(object),
                                               new[]
                {
                    target.GetType(),
                    typeof(IExportLocatorScope),
                    typeof(IDisposalScope),
                    typeof(IInjectionContext)
                },
                                               target.GetType(),
                                               true);

                request.ILGenerator = method.GetILGenerator();

                if (!TryGenerateIL(request, finalExpression))
                {
                    return(false);
                }

                request.ILGenerator.Emit(OpCodes.Ret);

                newDelegate = (ActivationStrategyDelegate)method.CreateDelegate(typeof(ActivationStrategyDelegate), target);

                return(true);
            }
            catch (Exception)
            {
                // ignore exception and compile linq expression normally
            }

            return(false);
        }
        /// <summary>
        /// Generate IL for ParameterExpression
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, ParameterExpression expression)
        {
            var expressionConstants = request.ExpressionRequest.Constants;

            if (expression == expressionConstants.ScopeParameter)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_1);

                return(true);
            }

            if (expression == expressionConstants.RootDisposalScope)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_2);

                return(true);
            }

            if (expression == expressionConstants.InjectionContextParameter)
            {
                request.ILGenerator.Emit(OpCodes.Ldarg_3);

                return(true);
            }

            for (int i = 0; i < request.ExtraParameters.Length; i++)
            {
                if (expression == request.ExtraParameters[i])
                {
                    switch (i)
                    {
                    case 0:
                        request.ILGenerator.Emit(OpCodes.Ldloc_0);
                        return(true);

                    case 1:
                        request.ILGenerator.Emit(OpCodes.Ldloc_1);
                        return(true);

                    case 2:
                        request.ILGenerator.Emit(OpCodes.Ldloc_2);
                        return(true);

                    case 3:
                        request.ILGenerator.Emit(OpCodes.Ldloc_3);
                        return(true);

                    default:
                        request.ILGenerator.Emit(OpCodes.Ldloc_S, i);
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Generate IL for new expression
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, NewExpression expression)
        {
            if (expression.Arguments.Any(argument => !request.TryGenerateIL(request, argument)))
            {
                return(false);
            }

            request.ILGenerator.Emit(OpCodes.Newobj, expression.Constructor);

            return(true);
        }
        /// <summary>
        /// Try to create IL from linq expression, this is called recursively as the expression is walked
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression to convert</param>
        /// <returns></returns>
        protected virtual bool TryGenerateIL(DynamicMethodGenerationRequest request, Expression expression)
        {
            if (expression == null)
            {
                return(true);
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Call:
                return(ImplementationFactory.Locate <ICallExpressionGenerator>()
                       .GenerateIL(request, (MethodCallExpression)expression));

            case ExpressionType.Constant:
                return(ImplementationFactory.Locate <IConstantExpressionGenerator>()
                       .GenerateIL(request, (ConstantExpression)expression));

            case ExpressionType.Convert:
                if (TryGenerateIL(request, ((UnaryExpression)expression).Operand))
                {
                    request.ILGenerator.Emit(OpCodes.Castclass, expression.Type);
                    return(true);
                }

                return(false);

            case ExpressionType.MemberInit:
                return(ImplementationFactory.Locate <IMemeberInitExpressionGenerator>()
                       .GenerateIL(request, (MemberInitExpression)expression));

            case ExpressionType.New:
                return(ImplementationFactory.Locate <INewExpressionGenerator>()
                       .GenerateIL(request, (NewExpression)expression));

            case ExpressionType.NewArrayInit:
                return(ImplementationFactory.Locate <IArrayInitExpressionGenerator>()
                       .GenerateIL(request, (NewArrayExpression)expression));

            case ExpressionType.Parameter:
                return(ImplementationFactory.Locate <IParameterExpressionGenerator>()
                       .GenerateIL(request, (ParameterExpression)expression));

            case ExpressionType.Assign:
                return(ImplementationFactory.Locate <IAssignExpressionGenerator>()
                       .GenerateIL(request, (BinaryExpression)expression));

            default:
                request.ToString();
                break;
            }

            return(false);
        }
        /// <summary>
        /// Generate IL for member init expression
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, MemberInitExpression expression)
        {
            if (!request.TryGenerateIL(request, expression.NewExpression))
            {
                return(false);
            }

            var instance = request.ILGenerator.DeclareLocal(expression.Type);

            request.ILGenerator.Emit(OpCodes.Stloc, instance);

            foreach (var binding in expression.Bindings)
            {
                if (binding.BindingType != MemberBindingType.Assignment)
                {
                    return(false);
                }

                request.ILGenerator.Emit(OpCodes.Ldloc, instance);

                if (!request.TryGenerateIL(request, ((MemberAssignment)binding).Expression))
                {
                    return(false);
                }

                var propertyInfo = binding.Member as PropertyInfo;

                if (propertyInfo != null)
                {
                    var setMethod = propertyInfo.SetMethod;

                    if (setMethod == null)
                    {
                        return(false);
                    }

                    request.ILGenerator.EmitMethodCall(setMethod);
                }
                else if (binding.Member is FieldInfo)
                {
                    request.ILGenerator.Emit(OpCodes.Stfld, (FieldInfo)binding.Member);
                }
                else
                {
                    return(false);
                }
            }

            request.ILGenerator.Emit(OpCodes.Ldloc, instance);

            return(true);
        }
        /// <summary>
        /// Generate IL for method call expression
        /// </summary>
        /// <param name="request">dynamic method request</param>
        /// <param name="expression">expression to convert</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, MethodCallExpression expression)
        {
            if (!request.TryGenerateIL(request, expression.Object))
            {
                return(false);
            }

            if (expression.Arguments.Any(expressionArgument => !request.TryGenerateIL(request, expressionArgument)))
            {
                return(false);
            }

            request.ILGenerator.EmitMethodCall(expression.Method);

            return(true);
        }
Exemple #9
0
        /// <summary>
        /// Generate IL for new array expression
        /// </summary>
        /// <param name="request">request for generation</param>
        /// <param name="expression">expression to convert</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, NewArrayExpression expression)
        {
            var arrayType          = expression.Type;
            var elementType        = arrayType.GetElementType();
            var elementIsValueType = elementType.GetTypeInfo().IsValueType;

            var arrayInstance = request.ILGenerator.DeclareLocal(arrayType);

            request.ILGenerator.EmitInt(expression.Expressions.Count);

            request.ILGenerator.Emit(OpCodes.Newarr, elementType);

            request.ILGenerator.Emit(OpCodes.Stloc, arrayInstance);

            var index = 0;

            foreach (var instanceExpression in expression.Expressions)
            {
                request.ILGenerator.Emit(OpCodes.Ldloc, arrayInstance);
                request.ILGenerator.EmitInt(index);

                index++;

                if (elementIsValueType)
                {
                    request.ILGenerator.Emit(OpCodes.Ldelema, elementType);
                }

                if (!request.TryGenerateIL(request, instanceExpression))
                {
                    return(false);
                }

                if (elementIsValueType)
                {
                    request.ILGenerator.Emit(OpCodes.Stobj, elementType);
                }
                else
                {
                    request.ILGenerator.Emit(OpCodes.Stelem_Ref);
                }
            }

            request.ILGenerator.Emit(OpCodes.Ldloc, arrayInstance);

            return(true);
        }
        private object CreateConstantTarget(DynamicMethodGenerationRequest request)
        {
            Type openType = null;

            switch (request.Constants.Count)
            {
            case 1:
                openType = typeof(DynamicMethodTarget <>);
                break;

            case 2:
                openType = typeof(DynamicMethodTarget <,>);
                break;

            case 3:
                openType = typeof(DynamicMethodTarget <, ,>);
                break;

            case 4:
                openType = typeof(DynamicMethodTarget <, , ,>);
                break;

            case 5:
                openType = typeof(DynamicMethodTarget <, , , ,>);
                break;

            case 6:
                openType = typeof(DynamicMethodTarget <, , , , ,>);
                break;

            case 7:
                openType = typeof(DynamicMethodTarget <, , , , , ,>);
                break;

            case 8:
                openType = typeof(DynamicMethodTarget <, , , , , , ,>);
                break;

            default:
                return(CreateArrayTarget(request));
            }

            var closedType = openType.MakeGenericType(request.Constants.Select(c => c.GetType()).ToArray());

            return(Activator.CreateInstance(closedType, request.Constants.ToArray()));
        }
Exemple #11
0
        private bool ProcessConstantFromTarget(DynamicMethodGenerationRequest request, ConstantExpression expression)
        {
            var constantIndex = request.Constants.IndexOf(expression.Value);

            if (constantIndex < 0)
            {
                return(false);
            }

            constantIndex++;

            var field = request.Target.GetType().GetRuntimeField("TArg" + constantIndex);

            request.ILGenerator.Emit(OpCodes.Ldarg_0);

            request.ILGenerator.Emit(OpCodes.Ldfld, field);

            return(true);
        }
Exemple #12
0
        /// <summary>
        /// Generate IL for a constant expression
        /// </summary>
        /// <param name="request">dynamic request</param>
        /// <param name="expression">constant expression to convert</param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, ConstantExpression expression)
        {
            if (expression.Value == null)
            {
                request.ILGenerator.Emit(OpCodes.Ldnull);

                return(true);
            }

            var expressionType = expression.Type;

            if (expressionType == typeof(int))
            {
                request.ILGenerator.EmitInt((int)expression.Value);
            }
            else if (expressionType == typeof(string))
            {
                request.ILGenerator.Emit(OpCodes.Ldstr, (string)expression.Value);
            }
            else if (expressionType == typeof(bool))
            {
                request.ILGenerator.Emit((bool)expression.Value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            }
            else if (expressionType == typeof(double))
            {
                request.ILGenerator.Emit(OpCodes.Ldc_R8, (double)expression.Value);
            }
            else if (request.IsArrayTarget)
            {
                return(ProcessConstantFromArrayTarget(request, expression));
            }
            else
            {
                return(ProcessConstantFromTarget(request, expression));
            }

            return(true);
        }
        /// <summary>
        /// Generate IL for assign statement
        /// </summary>
        /// <param name="request"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public bool GenerateIL(DynamicMethodGenerationRequest request, BinaryExpression expression)
        {
            if (request.TryGenerateIL(request, expression.Right))
            {
                for (int i = 0; i < request.ExtraParameters.Length; i++)
                {
                    if (expression.Left == request.ExtraParameters[i])
                    {
                        switch (i)
                        {
                        case 0:
                            request.ILGenerator.Emit(OpCodes.Stloc_0);
                            return(true);

                        case 1:
                            request.ILGenerator.Emit(OpCodes.Stloc_1);
                            return(true);

                        case 2:
                            request.ILGenerator.Emit(OpCodes.Stloc_2);
                            return(true);

                        case 3:
                            request.ILGenerator.Emit(OpCodes.Stloc_3);
                            return(true);

                        default:
                            request.ILGenerator.Emit(OpCodes.Stloc_S, i);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        /// <summary>
        /// Try to create IL from linq expression, this is called recursively as the expression is walked
        /// </summary>
        /// <param name="request">request</param>
        /// <param name="expression">expression to convert</param>
        /// <returns></returns>
        protected virtual bool TryGenerateIL(DynamicMethodGenerationRequest request, Expression expression)
        {
            if (expression == null)
            {
                return(true);
            }

            switch (expression.NodeType)
            {
            case ExpressionType.Call:
                return(ImplementationFactory.Locate <ICallExpressionGenerator>()
                       .GenerateIL(request, (MethodCallExpression)expression));

            case ExpressionType.Constant:
                return(ImplementationFactory.Locate <IConstantExpressionGenerator>()
                       .GenerateIL(request, (ConstantExpression)expression));

            case ExpressionType.MemberInit:
                return(ImplementationFactory.Locate <IMemeberInitExpressionGenerator>()
                       .GenerateIL(request, (MemberInitExpression)expression));

            case ExpressionType.New:
                return(ImplementationFactory.Locate <INewExpressionGenerator>()
                       .GenerateIL(request, (NewExpression)expression));

            case ExpressionType.NewArrayInit:
                return(ImplementationFactory.Locate <IArrayInitExpressionGenerator>()
                       .GenerateIL(request, (NewArrayExpression)expression));

            case ExpressionType.Parameter:
                return(ImplementationFactory.Locate <IParameterExpressionGenerator>()
                       .GenerateIL(request, (ParameterExpression)expression));
            }

            return(false);
        }
        /// <summary>
        /// try to create delegate using IL generation
        /// </summary>
        /// <param name="expressionContext">expression context</param>
        /// <param name="parameters"></param>
        /// <param name="extraExpressions"></param>
        /// <param name="finalExpression">final expression to convert</param>
        /// <param name="newDelegateType">created delegate</param>
        /// <returns>true if delegate was created</returns>
        public virtual Delegate TryCreateDelegate(IActivationExpressionResult expressionContext, ParameterExpression[] parameters, Expression[] extraExpressions, Expression finalExpression, Type newDelegateType)
        {
            try
            {
                var request = new DynamicMethodGenerationRequest(expressionContext, TryGenerateIL, parameters);

                var constants = new List <object>();

                foreach (var expression in extraExpressions)
                {
                    if (!ImplementationFactory.Locate <IConstantExpressionCollector>().GetConstantExpressions(expression, constants))
                    {
                        return(null);
                    }
                }

                if (!ImplementationFactory.Locate <IConstantExpressionCollector>().GetConstantExpressions(finalExpression, constants))
                {
                    return(null);
                }

                request.Constants = constants;

                var target = ImplementationFactory.Locate <IDynamicMethodTargetCreator>().CreateMethodTarget(request);

                request.Target = target;

                var invokeMethod = newDelegateType.GetTypeInfo().GetDeclaredMethod("Invoke");

                var parameterTypes = new List <Type>();

                if (target != null)
                {
                    parameterTypes.Add(target.GetType());
                }

                parameterTypes.AddRange(invokeMethod.GetParameters().Select(p => p.ParameterType));

                var method = new DynamicMethod(string.Empty,
                                               invokeMethod.ReturnType,
                                               parameterTypes.ToArray(),
                                               typeof(LinqToDynamicMethodConverter),
                                               true);

                request.ILGenerator = method.GetILGenerator();

                foreach (var parameter in parameters)
                {
                    request.ILGenerator.DeclareLocal(parameter.Type);
                }

                foreach (var expression in extraExpressions)
                {
                    if (!TryGenerateIL(request, expression))
                    {
                        return(null);
                    }
                }

                if (!TryGenerateIL(request, finalExpression))
                {
                    return(null);
                }

                request.ILGenerator.Emit(OpCodes.Ret);

                return(method.CreateDelegate(newDelegateType, target));
            }
            catch (Exception exp)
            {
                expressionContext.Request.RequestingScope.ScopeConfiguration.Trace?.Invoke($"Exception thrown while compiling dynamic method {exp.Message}");
            }

            return(null);
        }
        private object CreateArrayTarget(DynamicMethodGenerationRequest request)
        {
            request.IsArrayTarget = true;

            return(new ArrayDynamicMethodTarget(request.Constants.ToArray()));
        }
        /// <summary>
        /// try to create delegate using IL generation
        /// </summary>
        /// <param name="expressionContext">expression context</param>
        /// <param name="parameters"></param>
        /// <param name="extraExpressions"></param>
        /// <param name="finalExpression">final expression to convert</param>
        /// <param name="newDelegate">created delegate</param>
        /// <returns>true if delegate was created</returns>
        public virtual bool TryCreateDelegate(IActivationExpressionResult expressionContext, ParameterExpression[] parameters, Expression[] extraExpressions, Expression finalExpression, out ActivationStrategyDelegate newDelegate)
        {
            newDelegate = null;

            try
            {
                var request = new DynamicMethodGenerationRequest(expressionContext, TryGenerateIL, parameters);

                var constants = new List <object>();

                foreach (var expression in extraExpressions)
                {
                    if (!ImplementationFactory.Locate <IConstantExpressionCollector>().GetConstantExpressions(expression, constants))
                    {
                        return(false);
                    }
                }

                if (!ImplementationFactory.Locate <IConstantExpressionCollector>().GetConstantExpressions(finalExpression, constants))
                {
                    return(false);
                }

                request.Constants = constants;

                var target = ImplementationFactory.Locate <IDynamicMethodTargetCreator>().CreateMethodTarget(request);

                if (target == null)
                {
                    return(false);
                }

                request.Target = target;

                var method = new DynamicMethod(string.Empty,
                                               typeof(object),
                                               new[]
                {
                    target.GetType(),
                    typeof(IExportLocatorScope),
                    typeof(IDisposalScope),
                    typeof(IInjectionContext)
                },
                                               target.GetType(),
                                               true);

                request.ILGenerator = method.GetILGenerator();

                foreach (var parameter in parameters)
                {
                    request.ILGenerator.DeclareLocal(parameter.Type);
                }


                foreach (var expression in extraExpressions)
                {
                    if (!TryGenerateIL(request, expression))
                    {
                        return(false);
                    }
                }

                if (!TryGenerateIL(request, finalExpression))
                {
                    return(false);
                }

                request.ILGenerator.Emit(OpCodes.Ret);

                newDelegate = (ActivationStrategyDelegate)method.CreateDelegate(typeof(ActivationStrategyDelegate), target);

                return(true);
            }
            catch (Exception exp)
            {
                expressionContext.Request.RequestingScope.ScopeConfiguration.Trace?.Invoke($"Exception thrown while compiling dynamic method {exp.Message}");
            }

            return(false);
        }
 /// <summary>
 /// Create method target based on request
 /// </summary>
 /// <param name="request">dynamic method request</param>
 /// <returns></returns>
 public object CreateMethodTarget(DynamicMethodGenerationRequest request)
 {
     return(request.Constants.Count == 0 ? new DynamicMethodTarget() : CreateConstantTarget(request));
 }