private static Action <IBindingBuilder>[] ConvertInternal(LambdaExpression expression, IBindingBuilder builder, bool ignoreCallback) { Expression lastExpression; string path; if (BindingExtensions.TryGetMemberPath(expression.Body, ".", false, out lastExpression, out path) && expression.Parameters[0] == lastExpression) { if (ignoreCallback) { builder.GetOrAddBindingSources().Add(context => BindingExtensions.CreateBindingSource(context, path, null)); return(Empty.Array <Action <IBindingBuilder> >()); } return(new Action <IBindingBuilder>[] { b => b.GetOrAddBindingSources().Add(context => BindingExtensions.CreateBindingSource(context, path, null)) }); } var visitor = new LambdaExpressionToBindingExpressionConverter(expression); visitor.ConvertInternal(expression); var actions = visitor._callbacks.ToArray(); visitor._members = null; visitor._sourceExpression = null; visitor._currentExpression = null; visitor._methodExpression = null; visitor._callbacks = null; return(actions); }
private void ConvertInternal(LambdaExpression expression) { var multiExpression = Visit(ContextReplacerVisitor.UpdateContextParameter(expression.Body)); if (_members.Count == 0) { AddBuildCallback(syntax => syntax.ToSource(context => BindingExtensions.CreateBindingSource(context, string.Empty, null))); } else { for (int i = 0; i < _members.Count; i++) { var value = _members[i].Value; AddBuildCallback(syntax => syntax.ToSource(value)); } } if (!(multiExpression is ParameterExpression)) { var func = Compile <IList <object> >(multiExpression, false); AddBuildCallback(syntax => syntax.Builder.Add(BindingBuilderConstants.MultiExpression, func)); } }
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); }