protected virtual void BindReflectionManager(IModuleContext context, IIocContainer container) { IReflectionManager reflectionManager = new ExpressionReflectionManager(); ServiceProvider.ReflectionManager = reflectionManager; container.BindToConstant(reflectionManager); }
internal static bool TryGetStaticValue <T>(this Expression expression, out T value, bool throwOnError) { try { object v; var exp = expression as ConstantExpression; if (exp == null) { v = ExpressionReflectionManager .CreateLambdaExpression(expression, Empty.Array <ParameterExpression>()) .Compile() .DynamicInvoke(Empty.Array <object>()); } else { v = exp.Value; } value = (T)BindingServiceProvider.ValueConverter(BindingMemberInfo.Empty, typeof(T), v); return(true); } catch (Exception e) { value = default(T); if (throwOnError) { throw ExceptionManager.ExpressionShouldBeStaticValue(expression, e); } return(false); } }
private Expression BuildLambdaExpression(ILambdaExpressionNode lambdaExpression) { if (_lambdaParameter == null) { throw BindingExceptionManager.UnexpectedExpressionNode(lambdaExpression); } var method = _lambdaParameter.ParameterType.GetMethodEx("Invoke", MemberFlags.Instance | MemberFlags.Public); if (method == null) { throw BindingExceptionManager.UnexpectedExpressionNode(lambdaExpression); } var parameters = method.GetParameters(); var lambdaParameters = new ParameterExpression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { lambdaParameters[i] = Expression.Parameter(parameters[i].ParameterType, lambdaExpression.Parameters[i]); } for (int index = 0; index < lambdaParameters.Length; index++) { var parameter = lambdaParameters[index]; _lambdaParameters.Add(parameter.Name, parameter); } var expression = BuildExpression(lambdaExpression.Expression); for (int index = 0; index < lambdaParameters.Length; index++) { _lambdaParameters.Remove(lambdaParameters[index].Name); } return(ExpressionReflectionManager.CreateLambdaExpression(expression, lambdaParameters)); }
private Func <IDataContext, TType, object> Compile <TType>(Expression multiExpression, bool withContext) where TType : IList <object> { var parameters = new ParameterExpression[_members.Count + 1]; parameters[0] = ContextExpression; for (int i = 0; i < _members.Count; i++) { parameters[i + 1] = _members[i].Key; } var @delegate = ExpressionReflectionManager .CreateLambdaExpression(multiExpression, parameters) .Compile(); Func <object[], object> exp; var methodInfo = @delegate.GetType().GetMethodEx("Invoke", MemberFlags.Public | MemberFlags.Instance); if (methodInfo == null) { exp = @delegate.DynamicInvoke; } else { Func <object, object[], object> invokeMethod = ServiceProvider.ReflectionManager.GetMethodDelegate(methodInfo); exp = objects => invokeMethod(@delegate, objects); } if (withContext) { return(exp.AsBindingExpressionWithContext <TType>); } return(exp.AsBindingExpression <TType>); }
private Expression BuildCondition(IConditionExpressionNode condition) { var ifTrue = BuildExpression(condition.IfTrue); var ifFalse = BuildExpression(condition.IfFalse); Convert(ref ifTrue, ref ifFalse, true); return(Expression.Condition(ExpressionReflectionManager.ConvertIfNeed(BuildExpression(condition.Condition), typeof(bool), true), ifTrue, ifFalse)); }
private Expression BuildMemberExpression(IMemberExpressionNode expression) { if (expression.Member.Contains("(")) { return(BuildMethodCall(new MethodCallExpressionNode(expression.Target, expression.Member.Replace("(", string.Empty).Replace(")", string.Empty), null, null))); } if (expression.Target == null) { Expression value; if (!_lambdaParameters.TryGetValue(expression.Member, out value)) { throw BindingExceptionManager.UnexpectedExpressionNode(expression); } return(value); } var target = BuildExpression(expression.Target); var type = GetTargetType(ref target); var @enum = BindingReflectionExtensions.TryParseEnum(expression.Member, type); if (@enum != null) { return(Expression.Constant(@enum)); } if (type != null) { var bindingMember = BindingServiceProvider .MemberProvider .GetBindingMember(type, expression.Member, false, false); if (bindingMember != null) { var methodCall = Expression.Call(Expression.Constant(bindingMember, typeof(IBindingMemberInfo)), BindingMemberGetValueMethod, ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false), EmptyObjectArrayExpression); return(Expression.Convert(methodCall, bindingMember.Type)); } } var member = type.FindPropertyOrField(expression.Member, target == null); //Trying to get dynamic value. if (member == null) { return(Expression.Call(null, GetMemberValueDynamicMethod, ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false), Expression.Constant(expression.Member, typeof(string)))); } return(member is PropertyInfo ? Expression.Property(target, (PropertyInfo)member) : Expression.Field(target, (FieldInfo)member)); }
/// <summary> /// Initializes a new instance of the <see cref="CompiledExpressionInvoker" /> class. /// </summary> public CompiledExpressionInvoker([NotNull] IExpressionNode node, IList <KeyValuePair <string, BindingMemberExpressionNode> > members, bool isEmpty) { Should.NotBeNull(node, "node"); _node = node; _isEmpty = isEmpty; _expressionCache = new Dictionary <CacheKey, Func <object[], object> >(CacheKeyComparer.Instance); _lambdaParameters = new Dictionary <string, Expression>(); _thisExpression = Expression.Constant(this); _nodeToExpressionMapping = new Dictionary <ExpressionNodeType, Func <IExpressionNode, Expression> > { { ExpressionNodeType.Binary, expressionNode => BuildBinary((IBinaryExpressionNode)expressionNode) }, { ExpressionNodeType.Condition, expressionNode => BuildCondition((IConditionExpressionNode)expressionNode) }, { ExpressionNodeType.Constant, expressionNode => BuildConstant((IConstantExpressionNode)expressionNode) }, { ExpressionNodeType.Index, expressionNode => BuildIndex((IIndexExpressionNode)expressionNode) }, { ExpressionNodeType.Member, expressionNode => BuildMemberExpression((IMemberExpressionNode)expressionNode) }, { ExpressionNodeType.MethodCall, expressionNode => BuildMethodCall((IMethodCallExpressionNode)expressionNode) }, { ExpressionNodeType.Unary, expressionNode => BuildUnary((IUnaryExressionNode)expressionNode) }, { ExpressionNodeType.BindingMember, expressionNode => BuildBindingMember((BindingMemberExpressionNode)expressionNode) }, { ExpressionNodeType.Lambda, expressionNode => BuildLambdaExpression((ILambdaExpressionNode)expressionNode) } }; _unaryToExpressionMapping = new Dictionary <TokenType, Func <Expression, Expression> > { { TokenType.Minus, Expression.Negate }, { TokenType.Exclamation, Expression.Not }, { TokenType.Tilde, Expression.Not } }; _binaryToExpressionMapping = new Dictionary <TokenType, Func <Expression, Expression, Expression> > { { TokenType.Asterisk, (expression, expression1) => GenerateNumericalExpression(expression, expression1, Expression.Multiply) }, { TokenType.Slash, (expression, expression1) => GenerateNumericalExpression(expression, expression1, Expression.Divide) }, { TokenType.Minus, (expression, expression1) => GenerateNumericalExpression(expression, expression1, Expression.Subtract) }, { TokenType.Percent, (expression, expression1) => GenerateNumericalExpression(expression, expression1, Expression.Modulo) }, { TokenType.Plus, GeneratePlusExpression }, { TokenType.Amphersand, (expression, expression1) => GenerateBooleanExpression(expression, expression1, Expression.And) }, { TokenType.DoubleAmphersand, (expression, expression1) => GenerateBooleanExpression(expression, expression1, Expression.AndAlso) }, { TokenType.Bar, (expression, expression1) => GenerateBooleanExpression(expression, expression1, Expression.Or) }, { TokenType.DoubleBar, (expression, expression1) => GenerateBooleanExpression(expression, expression1, Expression.OrElse) }, { TokenType.DoubleEqual, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.Equal) }, { TokenType.ExclamationEqual, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.NotEqual) }, { TokenType.GreaterThan, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.GreaterThan) }, { TokenType.GreaterThanEqual, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.GreaterThanOrEqual) }, { TokenType.LessThan, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.LessThan) }, { TokenType.LessThanEqual, (expression, expression1) => GenerateEqualityExpression(expression, expression1, Expression.LessThanOrEqual) }, { TokenType.Equal, (expression, expression1) => ExpressionReflectionManager.Assign(expression, ExpressionReflectionManager.ConvertIfNeed(expression1, expression.Type, false)) }, { TokenType.DoubleQuestion, (expression, expression1) => { Convert(ref expression, ref expression1, true); return(Expression.Coalesce(expression, expression1)); } } }; }
private static Expression GenerateEqual(Expression left, Expression right) { Convert(ref left, ref right, true); try { return(Expression.Equal(left, right)); } catch { return(Expression.Call(null, EqualsMethod, ExpressionReflectionManager.ConvertIfNeed(left, typeof(object), false), ExpressionReflectionManager.ConvertIfNeed(right, typeof(object), false))); } }
private static void Convert(ref Expression left, ref Expression right, bool exactly) { if (left.Type.Equals(right.Type)) { return; } if (left.Type.IsCompatibleWith(right.Type)) { left = ExpressionReflectionManager.ConvertIfNeed(left, right.Type, exactly); } else if (right.Type.IsCompatibleWith(left.Type)) { right = ExpressionReflectionManager.ConvertIfNeed(right, left.Type, exactly); } }
protected virtual Func <object[], object> CreateDelegate() { var expression = BuildExpression(_node); var @delegate = ExpressionReflectionManager .CreateLambdaExpression(expression, Parameters.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToArray()) .Compile(); var methodInfo = @delegate.GetType().GetMethodEx("Invoke", MemberFlags.Public | MemberFlags.Instance); if (methodInfo == null) { return(@delegate.DynamicInvoke); } var invokeMethod = ServiceProvider.ReflectionManager.GetMethodDelegate(methodInfo); return(objects => invokeMethod(@delegate, objects)); }
private Expression BuildMethodCall(IMethodCallExpressionNode methodCall) { if (methodCall.Target == null) { throw BindingExceptionManager.UnexpectedExpressionNode(methodCall); } var typeArgs = GetTypes(methodCall.TypeArgs); var hasLambda = methodCall.Arguments .OfType <ILambdaExpressionNode>() .Any(); if (methodCall.Target.NodeType == ExpressionNodeType.DynamicMember) { if (hasLambda) { throw BindingExceptionManager.UnexpectedExpressionNode(methodCall); } var parameters = methodCall.Arguments .Select(node => ExpressionReflectionManager.ConvertIfNeed(BuildExpression(node), typeof(object), false)); var arrayArg = Expression.NewArrayInit(typeof(object), parameters); Type returnType = typeof(object); var dynamicMethod = BindingServiceProvider .ResourceResolver .ResolveMethod(methodCall.Method, _dataContext, false); if (dynamicMethod != null) { returnType = dynamicMethod.GetReturnType(arrayArg.Expressions.ToArrayEx(expression => expression.Type), typeArgs, DataContext); } return(ExpressionReflectionManager.ConvertIfNeed(Expression.Call(_thisExpression, ProxyMethod, Expression.Constant(methodCall.Method), DataContextParameter, Expression.Constant(typeArgs, typeof(IList <Type>)), arrayArg), returnType, false)); } var target = BuildExpression(methodCall.Target); var type = GetTargetType(ref target); var targetData = new ArgumentData(methodCall.Target, target, type); var args = methodCall .Arguments .ToArrayEx(node => new ArgumentData(node, node.NodeType == ExpressionNodeType.Lambda ? null : BuildExpression(node), null)); var method = targetData .FindMethod(methodCall.Method, typeArgs, args, BindingServiceProvider.ResourceResolver.GetKnownTypes(), target == null); return(GenerateMethodCall(method, targetData, args)); }
private static Expression[] ConvertParameters(ParameterInfo[] parameters, IList <Expression> args, bool hasParams) { var result = new Expression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { //optional or params if (i > args.Count - 1) { for (int j = i; j < parameters.Length; j++) { if (j == parameters.Length - 1 && hasParams) { var type = parameters[j].ParameterType.GetElementType(); result[j] = Expression.NewArrayInit(type); } else { result[j] = ExpressionReflectionManager.ConvertIfNeed(Expression.Constant(parameters[j].DefaultValue), parameters[j].ParameterType, false); } } break; } if (i == parameters.Length - 1 && hasParams && !args[i].Type.IsCompatibleWith(parameters[i].ParameterType)) { var arrayType = parameters[i].ParameterType.GetElementType(); var arrayArgs = new Expression[args.Count - i]; for (int j = i; j < args.Count; j++) { arrayArgs[j - i] = ExpressionReflectionManager.ConvertIfNeed(args[j], arrayType, false); } result[i] = Expression.NewArrayInit(arrayType, arrayArgs); } else { result[i] = ExpressionReflectionManager.ConvertIfNeed(args[i], parameters[i].ParameterType, false); } } return(result); }
private Expression BuildIndex(IIndexExpressionNode indexer) { if (indexer.Object == null) { throw BindingExceptionManager.UnexpectedExpressionNode(indexer); } var target = BuildExpression(indexer.Object); if (target.Type.IsArray) { return(Expression.ArrayIndex(target, indexer.Arguments.Select(BuildExpression))); } var type = GetTargetType(ref target); var targetData = new ArgumentData(indexer.Object, target, type, target == null); var args = indexer .Arguments .ToArrayEx(node => new ArgumentData(node, node.NodeType == ExpressionNodeType.Lambda ? null : BuildExpression(node), null, false)); var exp = TryGenerateMethodCall(targetData.FindIndexer(args, target == null), targetData, args); if (exp != null) { return(exp); } var arrayArgs = new Expression[args.Length]; for (int i = 0; i < args.Length; i++) { var data = args[i]; if (data.IsLambda || data.Expression == null) { throw BindingExceptionManager.InvalidBindingMember(type, ReflectionExtensions.IndexerName); } arrayArgs[i] = ExpressionReflectionManager.ConvertIfNeed(data.Expression, typeof(object), false); } return(Expression.Call(GetIndexValueDynamicMethod, ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false), Expression.NewArrayInit(typeof(object), arrayArgs), Expression.Constant(new MethodInvoker()), DataContextParameter)); }
private static Expression[] ConvertParameters(MethodBase method, Expression[] args) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1 && parameters[0].IsDefined(typeof(ParamArrayAttribute), true)) { var elementType = parameters[0].ParameterType.GetElementType(); var initializers = new Expression[args.Length]; for (int i = 0; i < args.Length; i++) { initializers[i] = ExpressionReflectionManager.ConvertIfNeed(args[i], elementType, false); } var array = Expression.NewArrayInit(elementType, initializers); return(new Expression[] { array }); } for (int index = 0; index < args.Length; index++) { Expression expression = args[index]; ParameterInfo parameter = parameters[index]; args[index] = ExpressionReflectionManager.ConvertIfNeed(expression, parameter.ParameterType, false); } return(args); }
private static Expression GenerateStringConcat(Expression left, Expression right) { return(Expression.Call(null, StringConcatMethod, ExpressionReflectionManager.ConvertIfNeed(left, typeof(object), false), ExpressionReflectionManager.ConvertIfNeed(right, typeof(object), false))); }
private static Expression GenerateStringConcat(Expression left, Expression right) { return(Expression.Call(null, typeof(string).GetMethodEx("Concat", new[] { typeof(object), typeof(object) }), new[] { ExpressionReflectionManager.ConvertIfNeed(left, typeof(object), false), ExpressionReflectionManager.ConvertIfNeed(right, typeof(object), false) })); }
public static Expression ProvideExpression(IBuilderSyntaxContext context) { var mExp = context.MethodExpression; var name = mExp.Method.Name; if (name == nameof(EventArgs)) { if (context.IsSameExpression()) { return(Expression.Convert(Expression.Call(GetEventArgsMethod, context.ContextParameter), mExp.Method.ReturnType)); } return(null); } if (name == nameof(Binding)) { if (context.IsSameExpression()) { return(Expression.Convert(Expression.Call(GetBindingMethod, context.ContextParameter), mExp.Method.ReturnType)); } return(null); } if (name == nameof(ResourceMethod)) { if (!context.IsSameExpression()) { return(null); } var typeArgsEx = Expression.NewArrayInit(typeof(Type), Expression.Constant(mExp.Method.ReturnType, typeof(Type))); return(Expression.Convert(Expression.Call(ResourceMethodImplMethod, mExp.Arguments[1], typeArgsEx, context.ContextParameter, mExp.Arguments[2]), context.Expression.Type)); } if (name == nameof(OneTime)) { if (!context.IsSameExpression()) { return(null); } DataConstant <object> id = Guid.NewGuid().ToString("n"); var idEx = Expression.Constant(id); var getBindEx = Expression.Call(GetBindingMethod, context.ContextParameter); var valueEx = Expression.Lambda(mExp.Arguments[1], Empty.Array <ParameterExpression>()); var method = GetOneTimeValueMethod.MakeGenericMethod(mExp.Arguments[1].Type); return(Expression.Call(method, new Expression[] { getBindEx, idEx, valueEx })); } if (name == nameof(GetErrors)) { if (!context.IsSameExpression()) { return(null); } var id = Guid.NewGuid(); var args = new List <Expression>(); var members = new List <string>(); var arrayExpression = mExp.Arguments[1] as NewArrayExpression; if (arrayExpression != null) { for (int i = 0; i < arrayExpression.Expressions.Count; i++) { var constantExpression = arrayExpression.Expressions[i] as ConstantExpression; if (constantExpression == null) { args.Add(arrayExpression.Expressions[i]); } else { members.Add((string)constantExpression.Value); } } } if (args.Count == 0) { args.Add(Expression.Call(ResourceMethodInfo.MakeGenericMethod(typeof(object)), Expression.Constant(null, typeof(IBindingSyntaxContext)), Expression.Constant(BindingServiceProvider.ResourceResolver.BindingSourceResourceName))); } context.AddBuildCallback(builder => { var behaviors = builder.GetOrAddBehaviors(); if (!behaviors.Any(behavior => behavior is NotifyDataErrorsAggregatorBehavior)) { behaviors.Clear(); behaviors.Add(new OneTimeBindingMode(false)); } behaviors.Add(new NotifyDataErrorsAggregatorBehavior(id) { ErrorPaths = members.ToArray() }); }); var array = Expression.NewArrayInit(typeof(object), args.Select(e => ExpressionReflectionManager.ConvertIfNeed(e, typeof(object), false))); return(Expression.Call(GetErrorsMethod, Expression.Constant(id), context.ContextParameter, array)); } Expression lastExpression; string path = string.Empty; if (!context.IsSameExpression() && !BindingExtensions.TryGetMemberPath(context.Expression, ".", false, out lastExpression, out path) && lastExpression != mExp) { return(null); } if (name == AttachedMemberConstants.DataContext) { return(context.GetOrAddParameterExpression(string.Empty, path, context.Expression, (dataContext, s) => BindingExtensions.CreateBindingSource(dataContext, s, null, true))); } if (name == nameof(Self) || name == nameof(Root) || name == nameof(Resource) || name == nameof(Source)) { string resourceName; switch (name) { case nameof(Self): resourceName = BindingServiceProvider.ResourceResolver.SelfResourceName; break; case nameof(Root): resourceName = BindingServiceProvider.ResourceResolver.RootElementResourceName; break; case nameof(Source): resourceName = BindingServiceProvider.ResourceResolver.BindingSourceResourceName; break; case nameof(Resource): mExp.Arguments[1].TryGetStaticValue(out resourceName, true); if (mExp.Arguments.Count == 3) { #pragma warning disable 618 LambdaExpression lambda = mExp.Arguments[2] as LambdaExpression; if (lambda == null) { lambda = (LambdaExpression)((UnaryExpression)mExp.Arguments[2]).Operand; } path = BindingExtensions.MergePath(lambda.GetMemberInfo().Name, path); #pragma warning restore 618 } break; default: mExp.Arguments[1].TryGetStaticValue(out resourceName, true); break; } return(context.GetOrAddParameterExpression("res:" + resourceName, path, context.Expression, (dataContext, s) => { var value = BindingServiceProvider .ResourceResolver .ResolveObject(resourceName, dataContext, true); return BindingExtensions.CreateBindingSource(dataContext, s, value); })); } if (name == nameof(Relative) || name == nameof(Element)) { object firstArg; if (mExp.Arguments.Count == 1) { firstArg = FirstLevelBoxed; } else { mExp.Arguments[1].TryGetStaticValue(out firstArg, true); } var relSource = name == nameof(Relative) ? new RelativeSourceInfo(mExp.Method.ReturnType.AssemblyQualifiedName, null, null, (uint)firstArg) : new RelativeSourceInfo(RelativeSourceInfo.ElementSourceType, firstArg.ToString(), null, 0); return(context .GetOrAddParameterExpression(name + mExp.Method.ReturnType.FullName, path, context.Expression, (dataContext, s) => BindingExtensions.CreateBindingSource(relSource, dataContext, dataContext.GetData(BindingBuilderConstants.Target), s))); } return(null); }
private Expression BuildMethodCall(IMethodCallExpressionNode methodCall) { if (methodCall.Target == null) { throw BindingExceptionManager.UnexpectedExpressionNode(methodCall); } var typeArgs = GetTypes(methodCall.TypeArgs); var hasLambda = methodCall.Arguments .OfType <ILambdaExpressionNode>() .Any(); if (methodCall.Target.NodeType == ExpressionNodeType.DynamicMember) { if (hasLambda) { throw BindingExceptionManager.UnexpectedExpressionNode(methodCall); } var parameters = methodCall.Arguments .Select(node => ExpressionReflectionManager.ConvertIfNeed(BuildExpression(node), typeof(object), false)); var arrayArg = Expression.NewArrayInit(typeof(object), parameters); Type returnType = typeof(object); var dynamicMethod = BindingServiceProvider .ResourceResolver .ResolveMethod(methodCall.Method, _dataContext, false); if (dynamicMethod != null) { returnType = dynamicMethod.GetReturnType(arrayArg.Expressions.ToArrayEx(expression => expression.Type), typeArgs, _dataContext); } return(ExpressionReflectionManager.ConvertIfNeed(Expression.Call(_thisExpression, ProxyMethod, Expression.Constant(methodCall.Method), DataContextParameter, Expression.Constant(typeArgs, typeof(IList <Type>)), arrayArg), returnType, false)); } var target = BuildExpression(methodCall.Target); var type = GetTargetType(ref target); var targetData = new ArgumentData(methodCall.Target, target, type, target == null); var args = methodCall .Arguments .ToArrayEx(node => new ArgumentData(node, node.NodeType == ExpressionNodeType.Lambda ? null : BuildExpression(node), null, false)); var types = new List <Type>(BindingServiceProvider.ResourceResolver.GetKnownTypes()) { typeof(BindingReflectionExtensions) }; var methods = targetData.FindMethod(methodCall.Method, typeArgs, args, types, target == null); var exp = TryGenerateMethodCall(methods, targetData, args); if (exp != null) { return(exp); } var arrayArgs = new Expression[args.Length]; for (int i = 0; i < args.Length; i++) { var data = args[i]; if (data.IsLambda || data.Expression == null) { throw BindingExceptionManager.InvalidBindingMember(type, methodCall.Method); } arrayArgs[i] = ExpressionReflectionManager.ConvertIfNeed(data.Expression, typeof(object), false); } if (target == null) { throw BindingExceptionManager.InvalidBindingMember(type, methodCall.Method); } return(Expression.Call(InvokeMemberDynamicMethod, ExpressionReflectionManager.ConvertIfNeed(target, typeof(object), false), Expression.Constant(methodCall.Method), Expression.NewArrayInit(typeof(object), arrayArgs), Expression.Constant(typeArgs), Expression.Constant(new MethodInvoker()), DataContextParameter)); }