コード例 #1
0
        public static BindingProxy GetValueProxy(IResourceContext context, string propertyKey)
        {
            var key = new BindingProxyKey(propertyKey);

            if (context.TryFindResource(key) is BindingProxy proxy)
            {
                return(proxy);
            }

            proxy = new BindingProxy();
            context.AddResource(key, proxy);
            return(proxy);
        }
コード例 #2
0
        private static IValidatorProvider CreateValidator(Type modelType, string propertyKey, ValueAttribute attribute, Func <string, object> deserializer)
        {
            Func <IResourceContext, IProxy> argumentProvider;
            var argument = attribute.Argument;

            if (argument is string expression)
            {
                var boundExpression = BoundExpression.Parse(expression);
                if (boundExpression.IsPlainString)
                {
                    var literal = new PlainObject(deserializer != null
                        ? deserializer(boundExpression.StringFormat)
                        : boundExpression.StringFormat);

                    argumentProvider = context => literal;
                }
                else
                {
                    var getString = boundExpression.StringFormat != null;
                    var action    = attribute.ArgumentUpdatedAction;
                    var notify    = action == ValidationAction.ClearErrors || action == ValidationAction.ValidateField;
                    argumentProvider = context =>
                    {
                        var value = getString
                            ? (IProxy)boundExpression.GetStringValue(context)
                            : boundExpression.GetValue(context);

                        if (notify)
                        {
                            value.ValueChanged = () =>
                            {
                                object model;
                                try
                                {
                                    model = context.GetModelInstance();
                                }
                                catch
                                {
                                    // Something went wrong so it's best to
                                    // disable the feature entirely.
                                    value.ValueChanged = null;
                                    return;
                                }

                                if (model is ExpandoObject && modelType == null)
                                {
                                    // Do nothing.
                                }
                                else if (model == null || model.GetType() != modelType)
                                {
                                    // Self dispose when form indicates model change.
                                    value.ValueChanged = null;
                                    return;
                                }

                                if (action == ValidationAction.ValidateField)
                                {
                                    ModelState.Validate(model, propertyKey);
                                }
                                else
                                {
                                    ModelState.ClearValidationErrors(model, propertyKey);
                                }
                            };
                        }

                        return(value);
                    };
                }
            }
            else
            {
                var literal = new PlainObject(argument);
                argumentProvider = context => literal;
            }

            BindingProxy ValueProvider(IResourceContext context)
            {
                var key = new BindingProxyKey(propertyKey);

                if (context.TryFindResource(key) is BindingProxy proxy)
                {
                    return(proxy);
                }

                proxy = new BindingProxy();
                context.AddResource(key, proxy);
                return(proxy);
            }

            Func <IResourceContext, IBoolProxy> isEnforcedProvider;

            switch (attribute.When)
            {
            case null:
                isEnforcedProvider = context => new PlainBool(true);
                break;

            case string expr:
                var boundExpression = BoundExpression.Parse(expr);
                if (!boundExpression.IsSingleResource)
                {
                    throw new ArgumentException(
                              "The provided value must be a bound resource or a literal bool value.", nameof(attribute));
                }

                isEnforcedProvider = context => boundExpression.GetBoolValue(context);
                break;

            case bool b:
                isEnforcedProvider = context => new PlainBool(b);
                break;

            default:
                throw new ArgumentException(
                          "The provided value must be a bound resource or a literal bool value.", nameof(attribute));
            }

            Func <IResourceContext, IErrorStringProvider> errorProvider;
            var message = attribute.Message;

            if (message == null)
            {
                switch (attribute.Condition)
                {
                case Must.BeGreaterThan:
                    message = "Value must be greater than {Argument}.";
                    break;

                case Must.BeGreaterThanOrEqualTo:
                    message = "Value must be greater than or equal to {Argument}.";
                    break;

                case Must.BeLessThan:
                    message = "Value must be less than {Argument}.";
                    break;

                case Must.BeLessThanOrEqualTo:
                    message = "Value must be less than or equal to {Argument}.";
                    break;

                case Must.BeEmpty:
                    message = "@Field must be empty.";
                    break;

                case Must.NotBeEmpty:
                    message = "@Field cannot be empty.";
                    break;

                default:
                    message = "@Invalid value.";
                    break;
                }
            }

            {
                var func            = new Func <IResourceContext, IProxy>(ValueProvider);
                var boundExpression = BoundExpression.Parse(message, new Dictionary <string, object>
                {
                    ["Value"]    = func,
                    ["Argument"] = argumentProvider
                });

                if (boundExpression.IsPlainString)
                {
                    var errorMessage = boundExpression.StringFormat;
                    errorProvider = context => new PlainErrorStringProvider(errorMessage);
                }
                else
                {
                    if (boundExpression.Resources.Any(
                            res => res is DeferredProxyResource resource && resource.ProxyProvider == func))
                    {
                        errorProvider =
                            context => new ValueErrorStringProvider(boundExpression.GetStringValue(context),
                                                                    ValueProvider(context));
                    }