我正在开发一个项目,我编写的API方法必须返回域对象的不同“视图”,如下所示:
namespace View.Product
{
public class SearchResult : View
{
public string Name { get; set; }
public decimal Price { get; set; }
}
public class Profile : View
{
public string Name { get; set; }
public decimal Price { get; set; }
[UseValidationRuleset("FreeText")]
public string Description { get; set; }
[SuppressValidation]
public string Comment { get; set; }
}
}
这些也是API中setter方法的参数,必须在将它们存储在DB中之前进行验证。我编写了一个对象验证器,允许用户在XML文件中定义验证规则集,并检查对象是否符合这些规则:
[Validatable]
public class View
{
[SuppressValidation]
public ValidationError[] ValidationErrors
{
get { return Validator.Validate(this); }
}
}
public static class Validator
{
private static Dictionary<string, Ruleset> Rulesets;
static Validator()
{
// read rulesets from xml
}
public static ValidationError[] Validate(object obj)
{
// check if obj is decorated with ValidatableAttribute
// if not, return an empty array (successful validation)
// iterate over the properties of obj
// - if the property is decorated with SuppressValidationAttribute,
// continue
// - if it is decorated with UseValidationRulesetAttribute,
// use the ruleset specified to call
// Validate(object value, string rulesetName, string FieldName)
// - otherwise, get the name of the property using reflection and
// use that as the ruleset name
}
private static List<ValidationError> Validate(object obj, string fieldName, string rulesetName)
{
// check if the ruleset exists, if not, throw exception
// call the ruleset's Validate method and return the results
}
}
public class Ruleset
{
public Type Type { get; set; }
public Rule[] Rules { get; set; }
public List<ValidationError> Validate(object property, string propertyName)
{
// check if property is of type Type
// if not, throw exception
// iterate over the Rules and call their Validate methods
// return a list of their return values
}
}
public abstract class Rule
{
public Type Type { get; protected set; }
public abstract ValidationError Validate(object value, string propertyName);
}
public class StringRegexRule : Rule
{
public string Regex { get; set; }
public StringRegexRule()
{
Type = typeof(string);
}
public override ValidationError Validate(object value, string propertyName)
{
// see if Regex matches value and return
// null or a ValidationError
}
}
Phew ...感谢您阅读所有这些内容。我已经实现了它并且它运行良好,我计划扩展它以验证IEnumerable字段和Validatable
的其他字段的内容。
[SuppressValidation]
。)这会使代码更加混乱(不需要在每个属性上使用[UseValidationRuleset("something")]
)但它在某种程度上感觉不对。我无法确定它是否可怕或令人敬畏。你觉得怎么样?答案 0 :(得分:1)
我的建议使用界面代替属性:
public interface IValidatable
{
ValidationError[] Validate(Rulesets ruleSets);
}
public class View : IValidatable
{
public ValidationError[] Validate(Rulesets ruleSets)
{
// do validate
}
}
public static class Validator
{
private static Rulesets _rulesets;
static Validator()
{
// read rulesets
}
public static ValidationError[] Validate(object obj)
{
IValidatable validObj = obj as IValidatable;
if (obj == null)
// not validatable
return new ValidationError[0];
return validObj.Validate(_rulesets);
}
}