简体   繁体   English

对象验证器-这是好的设计吗?

[英]Object validator - is this good design?

I'm working on a project where the API methods I write have to return different "views" of domain objects, like this: 我正在一个项目中,我编写的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; }
    }
}

These are also the arguments of setter methods in the API which have to be validated before storing them in the DB. 这些也是API中setter方法的参数,在将它们存储在数据库中之前必须进行验证。 I wrote an object validator that lets the user define validation rulesets in an XML file and checks if an object conforms to those rules: 我编写了一个对象验证器,使用户可以在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... Thanks for reading all of this. ew ...感谢您阅读所有这些内容。 I've already implemented it and it works nicely, and I'm planning to extend it to validate the contents of IEnumerable fields and other fields that are Validatable . 我已经实现了它,并且效果很好,并且我计划对其进行扩展以验证IEnumerable字段和Validatable其他字段的内容。

  • What I'm particularly concerned about is that if no ruleset is specified, the validator tries to use the name of the property as the ruleset name. 我特别担心的是,如果未指定任何规则集,那么验证器将尝试使用属性名称作为规则集名称。 (If you don't want that behavior, you can use [SuppressValidation] .) This makes the code much less cluttered (no need to use [UseValidationRuleset("something")] on every single property) but it somehow doesn't feel right. (如果您不希望出现这种情况,则可以使用[SuppressValidation] 。)这使代码更加混乱(无需在每个属性上都使用[UseValidationRuleset("something")] ),但它却感觉不到对。 I can't decide if it's awful or awesome. 我无法确定这是可怕还是可怕。 What do you think? 你怎么看?
  • Any suggestions on the other parts of this design are welcome too. 也欢迎对此设计的其他部分提出任何建议。 I'm not very experienced and I'm grateful for any help. 我经验不足,也很感谢您的帮助。
  • Also, is "Validatable" a good name? 另外,“ Validatable”是一个好名字吗? To me, it sounds pretty weird but I'm not a native English speaker. 对我来说,这听起来很奇怪,但我不是英语母语人士。

My suggestion uses an interface instead attributes: 我的建议使用接口代替属性:

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

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

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