应用运行时元数据类型进行验证
我需要对同一个对象进行不同的验证。所以我想使用 Metadatatype 来定义不同的规则,代码如下:
public class ValidateObjectAttribute : ValidationAttribute
{
private readonly Type _validationMetaDataType;
public ValidateObjectAttribute(Type validationMetaDataType)
{
_validationMetaDataType = validationMetaDataType;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var modelType = value.GetType();
AssociatedMetadataTypeTypeDescriptionProvider associatedMetadataTypeTypeDescriptionProvider = null;
if (_validationMetaDataType != null)
{
associatedMetadataTypeTypeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(modelType, _validationMetaDataType);
TypeDescriptor.AddProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
}
var validationctx = new ValidationContext(value);
var results = new List<ValidationResult>();
Validator.TryValidateObject(value, validationctx, results, true);
if (associatedMetadataTypeTypeDescriptionProvider != null)
{
TypeDescriptor.RemoveProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
TypeDescriptor.Refresh(value);
}
if (results.Count == 0) return ValidationResult.Success;
return new ValidationResult($"Validation fail for prop: {validationContext.DisplayName}");
}
}
public class BarMetaData1
{
[Required]
public string BarField1;
[Required]
public string BarField2;
}
public class FooMetaData1
{
[Required]
public string FooField1;
[Required]
public string FooField2;
[Required, ValidateObject(typeof(BarMetaData1))]
public Bar FooObject1;
}
public class FooMetaData2
{
public string FooField1;
[Required]
public string FooField2;
[Required, ValidateObject(typeof(BarMetaData1))]
public Bar FooObject1;
}
public class BaseValidation
{
public bool IsValid(Type validationMetaDataType)
{
var modelType = this.GetType();
AssociatedMetadataTypeTypeDescriptionProvider associatedMetadataTypeTypeDescriptionProvider = null;
if (validationMetaDataType != null)
{
associatedMetadataTypeTypeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(modelType, validationMetaDataType);
TypeDescriptor.AddProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
TypeDescriptor.Refresh(this);
}
var validationctx = new ValidationContext(this);
var results = new List<ValidationResult>();
Validator.TryValidateObject(this, validationctx, results, true);
if (associatedMetadataTypeTypeDescriptionProvider != null)
{
TypeDescriptor.RemoveProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
}
return results.Count == 0;
}
}
public class Foo : BaseValidation
{
public string FooField1 { get; set; }
public string FooField2 { get; set; }
public Bar FooObject1 { get; set; }
}
public class Bar
{
public string BarField1 { get; set; }
public string BarField2 { get; set; }
}
验证以这种方式调用:
public void Index()
{
Foo fooInstance = new Foo()
{
FooObject1 = new Bar()
};
fooInstance.IsValid(typeof(FooMetaData2));
fooInstance.IsValid(typeof(FooMetaData1));
Foo fooInstance2 = new Foo()
{
FooObject1 = new Bar()
};
fooInstance2.IsValid(typeof(FooMetaData2));
}
问题是什么:
- 第一次验证 [fooInstance.IsValid(typeof(FooMetaData2))] 是正确的(缺少 2 个必填字段) ,
- 第二次验证调用 [fooInstance.IsValid(typeof(FooMetaData1))] 结果错误(缺少 3 个必填字段,但代码只通知我 2),似乎代码应用了 FooMetaData2 类中描述的验证而不是FooMetaData1
有人可以向我解释为什么吗? 谢谢
I need to have different validation for the same object. So I thought to use Metadatatype to define the different rules the code is below:
public class ValidateObjectAttribute : ValidationAttribute
{
private readonly Type _validationMetaDataType;
public ValidateObjectAttribute(Type validationMetaDataType)
{
_validationMetaDataType = validationMetaDataType;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var modelType = value.GetType();
AssociatedMetadataTypeTypeDescriptionProvider associatedMetadataTypeTypeDescriptionProvider = null;
if (_validationMetaDataType != null)
{
associatedMetadataTypeTypeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(modelType, _validationMetaDataType);
TypeDescriptor.AddProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
}
var validationctx = new ValidationContext(value);
var results = new List<ValidationResult>();
Validator.TryValidateObject(value, validationctx, results, true);
if (associatedMetadataTypeTypeDescriptionProvider != null)
{
TypeDescriptor.RemoveProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
TypeDescriptor.Refresh(value);
}
if (results.Count == 0) return ValidationResult.Success;
return new ValidationResult(quot;Validation fail for prop: {validationContext.DisplayName}");
}
}
public class BarMetaData1
{
[Required]
public string BarField1;
[Required]
public string BarField2;
}
public class FooMetaData1
{
[Required]
public string FooField1;
[Required]
public string FooField2;
[Required, ValidateObject(typeof(BarMetaData1))]
public Bar FooObject1;
}
public class FooMetaData2
{
public string FooField1;
[Required]
public string FooField2;
[Required, ValidateObject(typeof(BarMetaData1))]
public Bar FooObject1;
}
public class BaseValidation
{
public bool IsValid(Type validationMetaDataType)
{
var modelType = this.GetType();
AssociatedMetadataTypeTypeDescriptionProvider associatedMetadataTypeTypeDescriptionProvider = null;
if (validationMetaDataType != null)
{
associatedMetadataTypeTypeDescriptionProvider = new AssociatedMetadataTypeTypeDescriptionProvider(modelType, validationMetaDataType);
TypeDescriptor.AddProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
TypeDescriptor.Refresh(this);
}
var validationctx = new ValidationContext(this);
var results = new List<ValidationResult>();
Validator.TryValidateObject(this, validationctx, results, true);
if (associatedMetadataTypeTypeDescriptionProvider != null)
{
TypeDescriptor.RemoveProvider(associatedMetadataTypeTypeDescriptionProvider, modelType);
}
return results.Count == 0;
}
}
public class Foo : BaseValidation
{
public string FooField1 { get; set; }
public string FooField2 { get; set; }
public Bar FooObject1 { get; set; }
}
public class Bar
{
public string BarField1 { get; set; }
public string BarField2 { get; set; }
}
the validation is call in this way:
public void Index()
{
Foo fooInstance = new Foo()
{
FooObject1 = new Bar()
};
fooInstance.IsValid(typeof(FooMetaData2));
fooInstance.IsValid(typeof(FooMetaData1));
Foo fooInstance2 = new Foo()
{
FooObject1 = new Bar()
};
fooInstance2.IsValid(typeof(FooMetaData2));
}
What is the issue:
- first validation [fooInstance.IsValid(typeof(FooMetaData2))] is right (2 mandatory fields missing),
- second validation call [fooInstance.IsValid(typeof(FooMetaData1))] the result is wrong (3 mandatory field missing but the code notify me only 2), it seems that the code apply the validation describe in FooMetaData2 class instead of FooMetaData1
Someone can explain to me why?
thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我使用 FluentValidator 插件解决了
I solved using fluentValidator plugin