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