C# 基于规则的验证层
我正在努力实现 从打电话的人开始,我想这样做:C# 基于规则的验证层,c#,validation,generics,design-patterns,C#,Validation,Generics,Design Patterns,我正在努力实现 从打电话的人开始,我想这样做: var validatore = new Validator(); validatore.AddRule<TestRule>("OK"); validatore.AddRule<int>(45); validatore.Validate(); public interface IValidator { void AddRule<TRule>(dynamic arg); ValidationR
var validatore = new Validator();
validatore.AddRule<TestRule>("OK");
validatore.AddRule<int>(45);
validatore.Validate();
public interface IValidator
{
void AddRule<TRule>(dynamic arg);
ValidationResult Validate();
}
public class Validator : IValidator
{
public void AddRule<T>(dynamic arg)
{
???
}
public ValidationResult Validate()
{
forEach ...
}
}
var Validator=new Validator();
验证人。添加规则(“确定”);
验证人。添加规则(45);
Validate.Validate();
规则的实施:
public interface IValidationRule<T>
{
string Error { get; set; }
bool Validate(T arg);
}
public class TestRule : IValidationRule<string>
{
public string Error { get; set; }
public bool Validate(string arg)
{
return arg == "test";
}
}
公共接口验证规则
{
字符串错误{get;set;}
bool验证(T参数);
}
公共类TestRule:IValidationRule
{
公共字符串错误{get;set;}
公共bool验证(字符串arg)
{
返回arg==“测试”;
}
}
问题是验证器的具体实现。
我假设是这样的:
var validatore = new Validator();
validatore.AddRule<TestRule>("OK");
validatore.AddRule<int>(45);
validatore.Validate();
public interface IValidator
{
void AddRule<TRule>(dynamic arg);
ValidationResult Validate();
}
public class Validator : IValidator
{
public void AddRule<T>(dynamic arg)
{
???
}
public ValidationResult Validate()
{
forEach ...
}
}
公共接口IValidator
{
void AddRule(动态参数);
ValidationResult Validate();
}
公共类验证器:IValidator
{
公共void AddRule(动态参数)
{
???
}
公共验证结果验证()
{
forEach。。。
}
}
我应该将每个通用规则放在单个集合对象(AddRule)的何处?
我的like实现是否正确?这种模式一开始就有点过于抽象。从某种意义上说,如果你从你想要做的事情开始,然后在上面进行抽象,那么你最终会得到更有用的概括。比如,在这种情况下,不明显的是,验证了什么?用户在某些UI中的输入?还是来自某个xml的数据?在第一种情况下,您不仅需要一条错误消息,还可能需要一些根据错误更新UI的操作。然后验证抽象可能会采取一种完全不同的形式。而实际的代码将从何而来,进行验证?如果必须为每个验证规则实现特殊类,那么当您实际想要使用它时,就会产生一个非常抽象但不必要的复杂代码 另外,只有在绝对没有其他方法的情况下,我才会使用动态类型 因此,假设您仍然感兴趣,下面的代码将用于验证引用类型。同样,如果您需要一个验证系统,那么需要验证的值类型通常是某个类的属性,但请记住它不是通用的
public class ValidationResult
{
public bool HasError { get; set; } = false;
public string ErrorText { get; set; } = "No error";
public void SetError(string errorMsg)
{
this.HasError = true;
ErrorText = errorMsg;
}
}
public interface IValidationRule
{
ValidationResult Validate();
}
public class ValidationRule<T> : IValidationRule
{
private Func<T, ValidationResult> validatorFunc;
private T validationSubject;
public ValidationRule(T validationSubject, Func<T, ValidationResult> validatorFunc)
{
this.validationSubject = validationSubject;
this.validatorFunc = validatorFunc;
}
public ValidationResult Validate() => validatorFunc?.Invoke(validationSubject);
}
public interface IValidator
{
void AddRule<T>(T validationSubject, Func<T, ValidationResult> validationFunc);
ValidationResult Validate();
}
public class Validator : IValidator
{
private readonly List<IValidationRule> rules = new List<IValidationRule>();
public void AddRule<T>(T validationSubject, Func<T,ValidationResult> validationFunc)
{
rules.Add(new ValidationRule<T>(validationSubject, validationFunc));
}
public ValidationResult Validate()
{
foreach (var rule in rules)
{
var result = rule.Validate();
if (result.HasError) return result;
}
return new ValidationResult();
}
}
这种模式一开始就有点过于抽象。从某种意义上说,如果你从你想要做的事情开始,然后在上面进行抽象,那么你最终会得到更有用的概括。比如,在这种情况下,不明显的是,验证了什么?用户在某些UI中的输入?还是来自某个xml的数据?在第一种情况下,您不仅需要一条错误消息,还可能需要一些根据错误更新UI的操作。然后验证抽象可能会采取一种完全不同的形式。而实际的代码将从何而来,进行验证?如果必须为每个验证规则实现特殊类,那么当您实际想要使用它时,就会产生一个非常抽象但不必要的复杂代码 另外,只有在绝对没有其他方法的情况下,我才会使用动态类型 因此,假设您仍然感兴趣,下面的代码将用于验证引用类型。同样,如果您需要一个验证系统,那么需要验证的值类型通常是某个类的属性,但请记住它不是通用的
public class ValidationResult
{
public bool HasError { get; set; } = false;
public string ErrorText { get; set; } = "No error";
public void SetError(string errorMsg)
{
this.HasError = true;
ErrorText = errorMsg;
}
}
public interface IValidationRule
{
ValidationResult Validate();
}
public class ValidationRule<T> : IValidationRule
{
private Func<T, ValidationResult> validatorFunc;
private T validationSubject;
public ValidationRule(T validationSubject, Func<T, ValidationResult> validatorFunc)
{
this.validationSubject = validationSubject;
this.validatorFunc = validatorFunc;
}
public ValidationResult Validate() => validatorFunc?.Invoke(validationSubject);
}
public interface IValidator
{
void AddRule<T>(T validationSubject, Func<T, ValidationResult> validationFunc);
ValidationResult Validate();
}
public class Validator : IValidator
{
private readonly List<IValidationRule> rules = new List<IValidationRule>();
public void AddRule<T>(T validationSubject, Func<T,ValidationResult> validationFunc)
{
rules.Add(new ValidationRule<T>(validationSubject, validationFunc));
}
public ValidationResult Validate()
{
foreach (var rule in rules)
{
var result = rule.Validate();
if (result.HasError) return result;
}
return new ValidationResult();
}
}
可能会有帮助。根据您的用例,您可以使用简单的集合,也可以使用更具体的集合(例如,如果您有多个线程添加验证器,则可以使用Concurrentlist),但您可能需要某种集合来保存您的所有规则Validator@Brezelmann这就是重点。我想我需要某种集合来迭代对象。关键是每个对象都有不同的类型,我不知道如何在单个结构中聚合它们。不是每个Validationrule都继承自IValidationRule接口吗?如果它们是,您可以使用它来使用一个集合,该集合可以容纳IvalidationRule的所有可能实现。您只需更新指定为类型的规则,然后将其放入集合中可能会有所帮助。根据您的用例,您可以使用简单的集合或更具体的集合(例如,如果您有多个线程添加验证程序,则可以使用Concurrentlist)但您可能需要某种集合来保存您的所有规则Validator@Brezelmann这就是重点。我想我需要某种集合来迭代对象。关键是每个对象都有不同的类型,我不知道如何在单个结构中聚合它们。不是每个Validationrule都继承自IValidationRule接口吗?如果它们是,您可以使用它来使用一个集合,该集合可以容纳IvalidationRule的所有可能实现。您只需重新创建指定为类型的规则,然后将其放入集合中