Exemple #1
0
        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));
        }
Exemple #2
0
        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));
        }
Exemple #3
0
 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)));
     }
 }
Exemple #4
0
 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);
     }
 }
Exemple #5
0
        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));
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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));
        }
Exemple #8
0
 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);
 }
Exemple #9
0
 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) }));
 }
Exemple #10
0
        /// <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));
                  } }
            };
        }
Exemple #11
0
 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)));
 }
Exemple #12
0
        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));
        }
Exemple #13
0
        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);
        }