使验证通用

本文关键字:验证 | 更新日期: 2023-09-27 18:25:49

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

注意:使通用<===>使类型独立

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

编辑

通用方法示例:在LINQ 中使用"OfType"

代码

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

使验证通用

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

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

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

NameRule<Employee> employeeNameRule = new NameRule<Employee>(x => x.name);
employeeManager.addRule(employeeNameRule);