我正在寻找创建一个ValidationRule类来验证实体类型对象的属性。我真的想设置要检查的属性的名称,然后为该类提供一个委托或一个lambda表达式,当对象运行其IsValid()方法时将在运行时计算该表达式。有没有人有这样的事情片段,或者有关如何将匿名方法作为参数或属性传递的任何想法?
另外,我不确定我是否在解释我想要完成的事情,所以如果我不清楚,请提出问题。
答案 0 :(得分:6)
实际上,您要使用的是Func<T,bool>
,其中T是您要验证的项目的类型。然后你会做这样的事情
validator.AddValidation(item => (item.HasEnoughInformation() || item.IsEmpty());
您可以将它们存储在List<Func<T,bool>>
。
答案 1 :(得分:3)
class ValidationRule {
public delegate bool Validator();
private Validator _v;
public ValidationRule(Validator v) { _v = v; }
public Validator Validator {
get { return _v; }
set { _v = value; }
}
public bool IsValid { get { return _v(); } }
}
var alwaysPasses = new ValidationRule(() => true);
var alwaysFails = new ValidationRule(() => false);
var textBoxHasText = new ValidationRule(() => textBox1.Text.Length > 0);
这应该让你开始。但是,真的,继承在这里更合适。问题只是Validator
无法访问任何未关闭的状态,这意味着它不像包含自己状态的ValidationRules
那样可重复使用。将以下类与先前的textBoxHasText
定义进行比较。
interface IValidationRule {
bool IsValid { get; }
}
class BoxHasText : IValidationRule {
TextBox _c;
public BoxHasText(TextBox c) { _c = c; }
public bool IsValid {
get { return _c.Text.Length > 0; }
}
}
答案 2 :(得分:2)
嗯,简单地说,如果你有一个Entity类,并且你想在该Entity上使用lambda表达式来确定某些东西是否有效(返回boolean),你可以使用一个Func。
所以,给定一个实体:
class Entity
{
public string MyProperty { get; set; }
}
你可以为此定义一个ValidationRule类:
class ValidationRule<T> where T : Entity
{
private Func<T, bool> _rule;
public ValidationRule(Func<T, bool> rule)
{
_rule = rule;
}
public bool IsValid(T entity)
{
return _rule(entity);
}
}
然后你可以像这样使用它:
var myEntity = new Entity() { MyProperty = "Hello World" };
var rule = new ValidationRule<Entity>(entity => entity.MyProperty == "Hello World");
var valid = rule.IsValid(myEntity);
当然,这只是一种可能的解决方案。
如果删除上面的通用约束(“where T:Entity”),您可以将其设置为可以与任何POCO一起使用的通用规则引擎。您不必为所需的每种用法派生类。因此,如果我想在TextBox上使用同一个类,我可以使用以下内容(删除通用约束后):
var rule = new ValidationRule<TextBox>(tb => tb.Text.Length > 0);
rule.IsValid(myTextBox);
这种方式非常灵活。一起使用lambda表达式和泛型非常强大。您可以接受表达式&gt;而不是接受Func或Action。或表达式&gt;并且可以直接访问快速树以自动调查诸如方法或属性的名称,表达式的类型等等。使用您的类的人不必更改单行代码。
答案 3 :(得分:1)
类似的东西:
class ValidationRule
{
private Func<bool> validation;
public ValidationRule(Func<bool> validation)
{
this.validation = validation;
}
public bool IsValid()
{
return validation();
}
}
将是更多C#3风格,但编译为与@Frank Krueger的答案相同的代码。 这就是你要求的,但感觉不对。是否有充分的理由说明实体无法扩展以执行验证?
答案 4 :(得分:0)
像这样的规则定义语法是否适合您?
public static void Valid(Address address, IScope scope)
{
scope.Validate(() => address.Street1, StringIs.Limited(10, 256));
scope.Validate(() => address.Street2, StringIs.Limited(256));
scope.Validate(() => address.Country, Is.NotDefault);
scope.Validate(() => address.Zip, StringIs.Limited(10));
switch (address.Country)
{
case Country.USA:
scope.Validate(() => address.Zip, StringIs.Limited(5, 10));
break;
case Country.France:
break;
case Country.Russia:
scope.Validate(() => address.Zip, StringIs.Limited(6, 6));
break;
default:
scope.Validate(() => address.Zip, StringIs.Limited(1, 64));
break;
}