首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使验证通用化

使验证通用化
EN

Stack Overflow用户
提问于 2012-02-27 05:13:35
回答 1查看 6.3K关注 0票数 0

我有以下C#代码。在这里,验证被保留在类之外,以满足开闭原则。这很好用。但面临的挑战是--验证不是通用的。它是特定于employee类(例如DateOfBirthRuleForEmployee)的。如何使所有对象(DateOfBirthRuleForAnyObject)的验证成为通用的。

注意:使泛型<==>使类型无关

注意:我也有NameLengthRuleForEmployee验证。未来可能会出现新的验证。

编辑

泛型方法示例:Using “OfType” in LINQ

代码

代码语言:javascript
复制
    class Program
    {
    static void Main(string[] args)
    {
        Employee employee = new Employee();
        employee.DateOfBirth = DateTime.Now;
        employee.Name = "Lijo";
        DateOfBirthRuleForEmployee dobRule = new
        DateOfBirthRuleForEmployee();
        NameLengthRuleForEmployee nameRule = new
        NameLengthRuleForEmployee();
        EmployeeManager employeeManager = new EmployeeManager();
        employeeManager.AddRules(dobRule);
        employeeManager.AddRules(nameRule);
        bool result = employeeManager.validateEntity(employee);
        Console.WriteLine(result);
        Console.ReadLine();
    }
}
public interface IEntity
{
}
public interface IRule<TEntity>
{
    bool IsValid(TEntity entity);
}
public class DateOfBirthRuleForEmployee : IRule<Employee>
{
    public bool IsValid(Employee entity)
    {
        return (entity.DateOfBirth.Year <= 1975);
    }
}
public class NameLengthRuleForEmployee : IRule<Employee>
{
    public bool IsValid(Employee employee)
    {
        return (employee.Name.Length < 5);
    }
}
public class Employee : IEntity
{
    private DateTime dateOfBirth;
    private string name;
    public DateTime DateOfBirth
    {
        get
        {
            return dateOfBirth;
        }
        set
        {
            dateOfBirth = value;
        }
    }
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }
}
public class EmployeeManager
{
    RulesEngine<Employee> engine = new RulesEngine<Employee>();
    public void AddRules(IRule<Employee> rule)
    {
        engine.AddRules(rule);
        //engine.AddRules(new NameLengthRuleForEmployee());
    }
    public bool validateEntity(Employee employee)
    {
        List<IRule<Employee>> rulesList = engine.GetRulesList();
        //No need for type checking. Overcame Invariance problem
        bool status = true;
        foreach (IRule<Employee> theRule in rulesList)
        {
            if (!theRule.IsValid(employee))
            {
                status = false;
                break;
            }
        }
        return status;
    }
}
public class RulesEngine<TEntity> where TEntity : IEntity
{
    private List<IRule<TEntity>> ruleList = new
    List<IRule<TEntity>>();
    public void AddRules(IRule<TEntity> rule)
    {
        //invariance is the key term
        ruleList.Add(rule);
    }
    public List<IRule<TEntity>> GetRulesList()
    {
        return ruleList;
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-02-27 05:42:14

挑战是让您的规则知道要验证哪种类型的属性。您可以通过实现一个提供了SLaks建议的接口,或者动态地请求它,或者提供一个具体的规则类,提供关于如何访问给定属性的更多信息,例如:

代码语言:javascript
复制
class NameRule<T> : IRule<T>  
{
    private Func<T, string> _nameAccessor;

    public NameRule(Func<T, string> nameAccessor)
    {
        _nameAccessor = nameAccessor;
    }

    public bool IsValid(T instance)
    {
        return _nameAccessor(instance).Length > 10;
    }
}

当然,这可以以下列方式使用:

代码语言:javascript
复制
NameRule<Employee> employeeNameRule = new NameRule<Employee>(x => x.name);
employeeManager.addRule(employeeNameRule);
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9460324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档