验证通用 [英] Making Validation Generic

查看:162
本文介绍了验证通用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下C#代码。这里的验证保存在课堂之外,以满足开放原则。这工作正常。但挑战在于 - 验证不是通用的。它特定于员工类(例如DateOfBirthRuleForEmployee)。我如何使所有对象的通用验证(DateOfBirthRuleForAnyObject)。注意:使通用< ==>使类型无关



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



编辑



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



CODE

  class程序
{
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;
私有字符串名称;
public DateTime DateOfBirth
{
get
{
return dateOfBirth;
}
set
{
dateOfBirth = value;
}
}
公共字符串名称
{
获取
{
返回名称;
}
set
{
name = value;
}
}
}
公共类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();
//不需要进行类型检查。克服不变性问题
bool status = true;
foreach(IRule< Employee> theRule in rulesList)
{
if(!theRule.IsValid(employee))
{
status = false;
休息;
}
}
返回状态;
}
}
public class RulesEngine< TEntity>其中TEntity:IEntity
{
private List< IRule< TEntity>> ruleList = new
List< IRule< TEntity>>();
public void AddRules(IRule< TEntity>规则)
{
//不变是关键术语
ruleList.Add(rule);
}
public List< IRule< TEntity>> GetRulesList()
{
return ruleList;
}
}


解决方案

challange是为了您的规则而知道哪种类型的属性需要验证。你可以通过实现一个接口来提供这个接口,该接口提供了SLak所建议的接口,或者动态地提供它,或者通过提供一个具体的规则类,提供更多关于如何访问给定属性的信息,例如:

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

可以通过以下方式使用这种方法: / p>

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


I have the following C# code. Here the validations are kept outside the class to satisfy Open – Closed Principle. This is working fine. But the challenge is – the validations are not generic. It is specific to employee class (E.g DateOfBirthRuleForEmployee). How do I make the validations generic for all objects (DateOfBirthRuleForAnyObject).

Note: Make Generic <==> Make Type-Independent

Note: I have NameLengthRuleForEmployee validation also. New validation may come in future.

EDIT

Generic Method Example: Using "OfType" in LINQ

CODE

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

解决方案

The challange is for your rules to know which property of what type to validate. You can either provide this by implementing an interface that provides just that as suggested by SLaks or by quessing it dynamically or by providing a concrete rule class with a bit more information on how to access the given property, e.g.:

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

this ofcourse can be used in the following way:

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

这篇关于验证通用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆