コード例 #1
0
        /// <summary>
        ///     Updates the relative source value.
        /// </summary>
        public void UpdateSource([NotNull] object target)
        {
            if (target == null)
            {
                throw BindingExceptionManager.InvalidBindingTarget(RelativeSourceNode.Path);
            }
            var path = RelativeSourceNode.Path ?? String.Empty;

            if (!String.IsNullOrEmpty(Path))
            {
                path = BindingExtensions.MergePath(path, Path);
            }


            if (RelativeSourceNode.Type != RelativeSourceExpressionNode.SelfType)
            {
                if (RelativeSourceNode.Type == RelativeSourceExpressionNode.MemberSourceType)
                {
                    target = BindingServiceProvider.ContextManager.GetBindingContext(target);
                }
                else
                {
                    target = new ParentSourceValue(target, RelativeSourceNode);
                }
            }
            IObserver observer = BindingServiceProvider.ObserverProvider.Observe(target, BindingPath.Create(path), false);

            _bindingSource = new BindingSource(observer);
        }
コード例 #2
0
        private IExpressionNode GetResourceMember(IExpressionNode node, string memberName, IList <IExpressionNode> nodes)
        {
            IExpressionNode staticValue;

            if (_staticNodes.TryGetValue(node, out staticValue))
            {
                return(staticValue);
            }

            IBindingPath path           = BindingServiceProvider.BindingPathFactory(memberName);
            string       firstMember    = path.Parts[0];
            Type         type           = BindingServiceProvider.ResourceResolver.ResolveType(firstMember, Context, false);
            var          resourceMember = (ResourceExpressionNode)nodes[0];

            if (resourceMember.Dynamic && type == null)
            {
                memberName = BindingExtensions.MergePath(path.Parts.Skip(1).ToArray());
                return(GetOrAddBindingMember("$" + path.Path, (s, i) => new BindingMemberExpressionNode(firstMember, memberName, s, i)));
            }

            bool            dynamicMember   = false;
            IExpressionNode firstMemberNode = nodes[1];

            if (!_staticNodes.TryGetValue(firstMemberNode, out staticValue))
            {
                if (type == null)
                {
                    var value = BindingServiceProvider
                                .ResourceResolver
                                .ResolveObject(firstMember, Context, true)
                                .Value;
                    var dynamicObject = value as IDynamicObject;
                    if (dynamicObject == null || path.Parts.Count <= 1)
                    {
                        staticValue = new ConstantExpressionNode(value);
                    }
                    else
                    {
                        staticValue   = new ConstantExpressionNode(dynamicObject.GetMember(path.Parts[1], Empty.Array <object>()));
                        dynamicMember = true;
                    }
                }
                else
                {
                    staticValue = new ConstantExpressionNode(type, typeof(Type));
                }
                _staticNodes[firstMemberNode] = staticValue;
                if (dynamicMember)
                {
                    _staticNodes[nodes[2]] = staticValue;
                }
            }
            if (firstMemberNode == node || (dynamicMember && node == nodes[2]))
            {
                return(staticValue);
            }
            return(node);
        }
コード例 #3
0
 public void MergePath(string path)
 {
     _path = BindingExtensions.MergePath(_path, path);
 }
コード例 #4
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);
        }
コード例 #5
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);
        }
コード例 #6
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);
        }