Ejemplo n.º 1
0
        private static Expression ProvideExpression(IBuilderSyntaxContext context)
        {
            var mExp = context.MethodExpression;
            var name = mExp.Method.Name;

            if (name == "EventArgs")
            {
                if (context.IsSameExpression())
                {
                    return(Expression.Convert(Expression.Call(GetEventArgsMethod, context.ContextParameter), mExp.Method.ReturnType));
                }
                return(null);
            }

            if (name == "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 == "OneTime")
            {
                if (!context.IsSameExpression())
                {
                    return(null);
                }
                var item      = Expression.Constant(new MacrosExpressionVisitor.OneTimeImpl());
                var parameter = Expression.Lambda(mExp.Arguments[1], Empty.Array <ParameterExpression>());
                return(Expression.Call(item, MacrosExpressionVisitor.OneTimeImpl.GetValueMethod.MakeGenericMethod(mExp.Arguments[1].Type), parameter));
            }

            if (name == "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(syntax =>
                {
                    var behaviors = syntax.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 == SelfMethodName || name == RootMethodName || name == ResourceMethodName || name == SourceMethodName)
            {
                string resourceName;
                switch (name)
                {
                case SelfMethodName:
                    resourceName = BindingServiceProvider.ResourceResolver.SelfResourceName;
                    break;

                case RootMethodName:
                    resourceName = BindingServiceProvider.ResourceResolver.RootElementResourceName;
                    break;

                case SourceMethodName:
                    resourceName = BindingServiceProvider.ResourceResolver.BindingSourceResourceName;
                    break;

                case ResourceMethodName:
                    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 == RelativeMethodName || name == "Element")
            {
                object firstArg;
                if (mExp.Arguments.Count == 1)
                {
                    firstArg = FirstLevelBoxed;
                }
                else
                {
                    mExp.Arguments[1].TryGetStaticValue(out firstArg, true);
                }
                var node = name == RelativeMethodName
                    ? RelativeSourceExpressionNode
                           .CreateRelativeSource(mExp.Method.ReturnType.AssemblyQualifiedName, (uint)firstArg, null)
                    : RelativeSourceExpressionNode.CreateElementSource(firstArg.ToString(), null);

                return(context
                       .GetOrAddParameterExpression(name + mExp.Method.ReturnType.FullName, path, context.Expression,
                                                    (dataContext, s) => BindingExtensions.CreateBindingSource(node, dataContext.GetData(BindingBuilderConstants.Target), s)));
            }
            return(null);
        }
Ejemplo n.º 2
0
        public IExpressionNode Visit(IExpressionNode node)
        {
            var member = node as IMemberExpressionNode;
            var resourceExpressionNode = member?.Target as ResourceExpressionNode;

            if (resourceExpressionNode != null)
            {
                //$self, $this --> $BindingServiceProvider.ResourceResolver.SelfResourceName
                if (member.Member == "self" || member.Member == "this")
                {
                    if (resourceExpressionNode.Dynamic)
                    {
                        return(new MemberExpressionNode(member.Target, BindingServiceProvider.ResourceResolver.SelfResourceName));
                    }
                    return(new MethodCallExpressionNode(member.Target, DefaultBindingParserHandler.GetSelfMethod, null, null));
                }
                //$context --> $BindingServiceProvider.ResourceResolver.DataContextResourceName
                if (member.Member == "context")
                {
                    return(new MemberExpressionNode(member.Target, BindingServiceProvider.ResourceResolver.DataContextResourceName));
                }
                //$args, $arg --> $GetEventArgs()
                if (member.Member == "args" || member.Member == "arg")
                {
                    return(new MethodCallExpressionNode(member.Target, DefaultBindingParserHandler.GetEventArgsMethod, null, null));
                }
                //$binding --> $GetBinding()
                if (member.Member == "binding")
                {
                    return(new MethodCallExpressionNode(member.Target, DefaultBindingParserHandler.GetBindingMethod, null, null));
                }
            }

            var methodCallExp = node as IMethodCallExpressionNode;

            if (methodCallExp != null && methodCallExp.Target is ResourceExpressionNode)
            {
                //$OneTime(Expression) --> oneTimeImpl.GetValue(GetBinding(), () => Expression)
                if (methodCallExp.Method == "OneTime" && methodCallExp.Arguments.Count == 1)
                {
                    DataConstant <object> constant = Guid.NewGuid().ToString("n");
                    var             idEx           = new ConstantExpressionNode(constant);
                    var             getBindEx      = new MethodCallExpressionNode(ResourceExpressionNode.DynamicInstance, DefaultBindingParserHandler.GetBindingMethod, null, null);
                    IExpressionNode getValueEx     = new LambdaExpressionNode(methodCallExp.Arguments[0], null);
                    return(new MethodCallExpressionNode(new ConstantExpressionNode(typeof(BindingExtensions)), "GetOrAddValue", new[]
                    {
                        getBindEx, idEx, getValueEx
                    }, null).Accept(this));
                }

                //Alias ($Format(), $MethodName, etc) --> type.Format()
                Type   type;
                string method;
                if (BindingServiceProvider.ResourceResolver.TryGetMethodAlias(methodCallExp.Method, out type, out method))
                {
                    return(new MethodCallExpressionNode(new ConstantExpressionNode(type), method, methodCallExp.Arguments, methodCallExp.TypeArgs).Accept(this));
                }
            }

            var    nodes      = new List <IExpressionNode>();
            var    members    = new List <string>();
            string memberName = node.TryGetMemberName(true, true, nodes, members);

            if (memberName == null)
            {
                var relativeExp = nodes[0] as IRelativeSourceExpressionNode;
                if (relativeExp != null)
                {
                    relativeExp.MergePath(BindingExtensions.MergePath(members));
                    return(relativeExp);
                }

                var methodCall = nodes[0] as IMethodCallExpressionNode;
                if (methodCall != null && methodCall.Target is ResourceExpressionNode)
                {
                    if (RelativeSourceAliases.Contains(methodCall.Method))
                    {
                        if ((methodCall.Arguments.Count == 1 || methodCall.Arguments.Count == 2) &&
                            methodCall.Arguments[0] is IMemberExpressionNode)
                        {
                            int level        = 1;
                            var relativeType = (IMemberExpressionNode)methodCall.Arguments[0];
                            if (methodCall.Arguments.Count == 2)
                            {
                                level = (int)((IConstantExpressionNode)methodCall.Arguments[1]).Value;
                            }
                            return(RelativeSourceExpressionNode.CreateRelativeSource(relativeType.Member, (uint)level,
                                                                                     BindingExtensions.MergePath(members)));
                        }
                    }

                    if (ElementSourceAliases.Contains(methodCall.Method))
                    {
                        if (methodCall.Arguments.Count == 1 && methodCall.Arguments[0] is IMemberExpressionNode)
                        {
                            var elementSource = (IMemberExpressionNode)methodCall.Arguments[0];
                            return(RelativeSourceExpressionNode.CreateElementSource(elementSource.Member,
                                                                                    BindingExtensions.MergePath(members)));
                        }
                    }
                }
            }
            return(node);
        }
Ejemplo n.º 3
0
        public IExpressionNode Visit(IExpressionNode node)
        {
            var member = node as IMemberExpressionNode;

            if (member != null && member.Target is ResourceExpressionNode)
            {
                //$self, $this --> $BindingServiceProvider.ResourceResolver.SelfResourceName
                if (member.Member == "self" || member.Member == "this")
                {
                    return(new MemberExpressionNode(member.Target, BindingServiceProvider.ResourceResolver.SelfResourceName));
                }
                //$context --> $BindingServiceProvider.ResourceResolver.DataContextResourceName
                if (member.Member == "context")
                {
                    return(new MemberExpressionNode(member.Target, BindingServiceProvider.ResourceResolver.DataContextResourceName));
                }
                //$args, $arg --> $GetEventArgs()
                if (member.Member == "args" || member.Member == "arg")
                {
                    return(new MethodCallExpressionNode(member.Target, DefaultBindingParserHandler.GetEventArgsMethod, Empty.Array <IExpressionNode>(), Empty.Array <string>()));
                }
            }

            var methodCallExp = node as IMethodCallExpressionNode;

            if (methodCallExp != null && methodCallExp.Target is ResourceExpressionNode)
            {
                //$Format() --> string.Format()
                if (methodCallExp.Method == "Format")
                {
                    return(new MethodCallExpressionNode(new ConstantExpressionNode(typeof(string)), methodCallExp.Method, methodCallExp.Arguments, methodCallExp.TypeArgs));
                }
                //$OneTime(Expression) --> oneTimeImpl.GetValue(() => Expression)
                if (methodCallExp.Method == "OneTime" && methodCallExp.Arguments.Count == 1)
                {
                    var             item      = new ConstantExpressionNode(new OneTimeImpl());
                    IExpressionNode parameter = new LambdaExpressionNode(methodCallExp.Arguments[0], null);
                    return(new MethodCallExpressionNode(item, OneTimeImpl.GetValueMethodName, new[] { parameter }, null));
                }
            }

            var    nodes      = new List <IExpressionNode>();
            var    members    = new List <string>();
            string memberName = node.TryGetMemberName(true, true, nodes, members);

            if (memberName == null)
            {
                var relativeExp = nodes[0] as IRelativeSourceExpressionNode;
                if (relativeExp != null)
                {
                    relativeExp.MergePath(BindingExtensions.MergePath(members));
                    return(relativeExp);
                }

                var methodCall = nodes[0] as IMethodCallExpressionNode;
                if (methodCall != null && methodCall.Target is ResourceExpressionNode)
                {
                    if (RelativeSourceAliases.Contains(methodCall.Method))
                    {
                        if ((methodCall.Arguments.Count == 1 || methodCall.Arguments.Count == 2) &&
                            methodCall.Arguments[0] is IMemberExpressionNode)
                        {
                            int level        = 1;
                            var relativeType = (IMemberExpressionNode)methodCall.Arguments[0];
                            if (methodCall.Arguments.Count == 2)
                            {
                                level = (int)((IConstantExpressionNode)methodCall.Arguments[1]).Value;
                            }
                            return(RelativeSourceExpressionNode.CreateRelativeSource(relativeType.Member, (uint)level,
                                                                                     BindingExtensions.MergePath(members)));
                        }
                    }

                    if (ElementSourceAliases.Contains(methodCall.Method))
                    {
                        if (methodCall.Arguments.Count == 1 && methodCall.Arguments[0] is IMemberExpressionNode)
                        {
                            var elementSource = (IMemberExpressionNode)methodCall.Arguments[0];
                            return(RelativeSourceExpressionNode.CreateElementSource(elementSource.Member,
                                                                                    BindingExtensions.MergePath(members)));
                        }
                    }
                }
            }
            return(node);
        }