Exemple #1
0
 private static bool IsSameExpression(this IBuilderSyntaxContext context)
 {
     return(context.MethodExpression == context.Expression);
 }
Exemple #2
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);
        }