0

我正在使用DataAnnotationAttributes 在 MVC 之外对我的模型上的属性应用验证。

public class MyModel
{
    [Required]
    [CustomValidation]
    public string Foo { get; set; }
}

我已经实现了以下扩展方法来验证模型。

public static void Validate(this object source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    var results = new List<ValidationResult>();
    bool IsValid = Validator.TryValidateObject(source, new ValidationContext(source, null, null), results, true);
    if (!IsValid)
        results.ForEach(r => { throw new ArgumentOutOfRangeException(r.ErrorMessage); });
 }

Validate()每次设置不方便的属性时,我都必须调用此方法:

MyModel model = new MyModel();
model.Foo = "bar";
model.Validate();

model.Foo = SomeMethod();
model.Validate();

我希望Validate()在模型状态发生变化时在幕后自动调用该方法。有人对如何实现这一目标有任何想法吗?

对于奖励积分,有人知道 MVC 是如何通过 实现这种自动验证的DataAnnotations吗?

谢谢。

4

1 回答 1

1

您可以使用代理包装您的类,拦截属性设置器并在每次设置器调用后验证对象。对于Castle DynamicProxy,这将是:

public class ValidationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();

        if (invocation.Method.IsSpecialName && invocation.Method.Name.StartsWith("set_"))
        {
            invocation.InvocationTarget.Validate();
        }
    }
}

然后,您将使用 DynamicProxy 而不是 operator new 创建模型:

ProxyGenerator proxyGenerator = new ProxyGenerator();
MyModel model = proxyGenerator.CreateClassProxy<MyModel>(new ValidationInterceptor());

model.Foo = "bar";

model.Foo = SomeMethod();

重要的是 MyModel 的所有属性都必须是虚拟的才能使代理工作:

public class MyModel
{
    public virtual string Foo { get; set; }
}
于 2014-01-09T09:56:37.300 回答