Exemple #1
0
        protected virtual void BindReflectionManager(IModuleContext context, IIocContainer container)
        {
            IReflectionManager reflectionManager = new ExpressionReflectionManager();

            ServiceProvider.ReflectionManager = reflectionManager;
            container.BindToConstant(reflectionManager);
        }
Exemple #2
0
 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);
     }
 }
Exemple #3
0
        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>);
        }
Exemple #5
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 #6
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 #7
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 #8
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 #9
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 #10
0
        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));
        }
Exemple #11
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 #12
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 #13
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 #14
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 #15
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 #16
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 #17
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);
        }
Exemple #18
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));
        }