简体   繁体   English

使用MVC外部的DataAnnotations自动进行模型验证

[英]Automatic Model Validation using DataAnnotations outside MVC

I am using DataAnnotation Attributes to apply validation to properties on my model, outside of MVC. 我正在使用DataAnnotation属性将验证应用于MVC之外的模型上的属性。

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

I have implemented the following extension method to validate the model. 我已经实现了以下扩展方法来验证模型。

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

I have to call this Validate() method every time I set a property which is not convenient: 每次设置不方便的属性时,我都必须调用此Validate()方法:

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

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

I would like that the Validate() method be called automatically behind the scenes when the state of the model changes. 我希望在模型状态更改时在后台自动调用Validate()方法。 Does anyone have any idead on how to achieve this? 是否有人对如何实现这一目标有任何想法?

For bonus points, does anyone know exactly how MVC achieve this automatic validation via DataAnnotations ? 对于奖励积分,没有人确切知道MVC如何通过DataAnnotations实现此自动验证吗?

Thanks. 谢谢。

You can wrap your classes with proxies , intercept property setters and validate object after each setter invocation. 您可以在每次setter调用之后使用proxies包装类,拦截属性setter和验证对象。 For Castle DynamicProxy this would be: 对于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();
        }
    }
}

Then you would create models with DynamicProxy instead of operator new: 然后,您将使用DynamicProxy而不是new运算符创建模型:

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

model.Foo = "bar";

model.Foo = SomeMethod();

It's important that all properties of MyModel must be virtual in order for proxy to work: 重要的是MyModel的所有属性都必须是虚拟的,以便代理工作:

public class MyModel
{
    public virtual string Foo { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM