我正在尝试对未绑定到 UI 的对象执行一些验证。例如我有这三个类:
public class XDeftable {
[ObjectCollectionValidator(typeof(XSchedGroup))]
public List<XSchedGroup> SCHED_GROUP { get; set; }
}
[IdentifyingProperty("TABLE_NAME")]
public class XSchedGroup {
[ObjectCollectionValidator(typeof(XJob))]
public List<XJob> JOB { get; set; }
[Required]
public string TABLE_NAME { get; set; }
}
[IdentifyingProperty("JOBNAME")]
public class XJob : ICalendar {
[Required]
public string JOBNAME { get; set; }
[Range(-62, 62)]
public string SHIFTNUM { get; set; }
[ObjectCollectionValidator(typeof(XTagNames))]
public List<XTagNames> TAG_NAMES { get; set; }
}
XDeftable -> XSchedGroup -> XJob -> XTagNames
当一个对象验证失败时,事情会完全按照预期工作,但如果我只是检查 ValidationResult 中的Key和Message,我最终会得到类似:“JOBNAME | Field is required”。
这样做的问题是,考虑到我可能在一个调度组中有数百个作业,验证是无用的,因为我不知道哪个特定作业失败了。我搜索了所有我能找到的关于验证和 C# 的文档,但没有找到任何获取更多数据的方法。我创建了属性 IdentificationingProperty 以允许我标记该类的哪个属性标识该类的特定实例。我有一个以前的自定义验证解决方案,我根据这个 Git Repo 进行了模拟:https ://github.com/reustmd/DataAnnotationsValidatorRecursive/tree/master/DataAnnotationsValidator/DataAnnotationsValidator 。它工作正常,但我想换成更强大的东西。
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class IdentifyingProperty : Attribute {
public string Name { get; set; }
public IdentifyingProperty(string name) {
this.Name = name;
}
}
到目前为止,我已经能够提出以下建议:
public ValidationResults Validate(XDeftable deftable) {
var results = new ObjectValidator(typeof(XDeftable)).Validate(deftable);
var detailedResults = new ValidationResults();
foreach (var item in results) {
var targetType = item.Target.GetType();
var identProp = targetType.GetCustomAttribute<IdentifyingProperty>();
if (identProp != null) {
var pi = targetType.GetProperty(identProp.Name);
var newKey = String.Format("{0}[{1}].{2}", targetType.Name, pi.GetValue(item.Target).ToString(), item.Key);
detailedResults.AddResult(new ValidationResult(item.Message, item.Target, newKey, item.Tag, item.Validator));
}
else {
detailedResults.AddResult(item);
}
}
return detailedResults;
}
这至少会返回“XJob[JOBNAME].SHIFTNUM | SHIFTNUM 字段必须介于 -62 和 62 之间”。如果有办法让我获得遵循容器链的结果,我仍然会喜欢它,例如:XSchedGroup[TABLE_NAME].XJob[JOBNAME].SHIFTNUM。