C#Lambda表达式或代理作为属性或参数

我正在寻找创建一个ValidationRule类来validation实体类型对象的属性。 我真的想设置要检查的属性的名称,然后为该类提供一个委托或一个lambda表达式,当对象运行其IsValid()方法时将在运行时计算该表达式。 有没有人有这样的事情片段,或者有关如何将匿名方法作为参数或属性传递的任何想法?

另外,我不确定我是否在解释我想要完成的事情,所以如果我不清楚,请提出问题。

真的,你想要使用的是Func ,其中T是你要validation的项目的类型。 然后你会做这样的事情

 validator.AddValidation(item => (item.HasEnoughInformation() || item.IsEmpty()); 

你可以将它们存储在List>

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

这应该让你开始。 但是,真的,inheritance在这里更合适。 问题很简单, Validator无法访问它没有关闭的任何状态,这意味着它不像ValidationRules那样可以重用,它包含自己的状态。 将以下类与textBoxHasText的先前定义进行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; } } } 

好吧,简单地说,如果你有一个Entity类,并且你想在该Entity上使用lambda表达式来确定某些东西是否有效(返回boolean),你可以使用一个Func。

所以,给定一个实体:

  class Entity { public string MyProperty { get; set; } } 

您可以为此定义ValidationRule类:

  class ValidationRule where T : Entity { private Func _rule; public ValidationRule(Func rule) { _rule = rule; } public bool IsValid(T entity) { return _rule(entity); } } 

然后你可以像这样使用它:

  var myEntity = new Entity() { MyProperty = "Hello World" }; var rule = new ValidationRule(entity => entity.MyProperty == "Hello World"); var valid = rule.IsValid(myEntity); 

当然,这只是一种可能的解决方案。

如果删除上面的通用约束(“where T:Entity”),则可以使其成为可以与任何POCO一起使用的通用规则引擎。 您不必为所需的每种用法派生类。 因此,如果我想在TextBox上使用同一个类,我可以使用以下内容(删除通用约束后):

  var rule = new ValidationRule(tb => tb.Text.Length > 0); rule.IsValid(myTextBox); 

这种方式非常灵活。 一起使用lambda表达式和generics非常强大。 您可以接受表达式>或表达式>而不是接受Func或Action,并可以直接访问表达式树以自动调查方法或属性的名称,表达的表达方式等等。并且人们使用您的class不必更改单行代码。

就像是:

 class ValidationRule { private Func validation; public ValidationRule(Func validation) { this.validation = validation; } public bool IsValid() { return validation(); } } 

将是更多的C#3风格,但编译成与@Frank Krueger的答案相同的代码。 这就是你要求的,但感觉不对。 是否有充分的理由说明实体无法扩展以执行validation?

像这样的规则定义语法是否适合您?

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

有关更多信息,请查看.NET中的DDD和规则驱动的UIvalidation