我正在使用DataAnnotation
属性将验证应用于我的模型上的属性,而不是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
实现此自动验证?
感谢。
答案 0 :(得分:1)
您可以使用proxies包装类,拦截属性设置器并在每次setter调用后验证对象。对于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; }
}