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); }
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); }
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); }