我一开始就坚持看起来非常简单的任务。我有一个类层次结构,每个类都可以定义自己的验证规则。定义验证规则应尽可能简单。以下几乎是所需要的:
class HierarchyBase
{
private List<Func<object, bool>> rules = new List<Func<object, bool>>();
public int fieldA = 0;
public HierarchyBase()
{
AddRule(x => ((HierarchyBase)x).fieldA % 2 == 0);
}
protected virtual void Operation()
{
fieldA++;
}
protected void AddRule(Func<object, bool> validCriterion)
{
rules.Add(validCriterion);
}
public void PerformOperation()
{
Operation();
Validate();
}
protected virtual void Operation()
{
fieldA++;
}
private void Validate()
{
IsValid = rules.All(x => x(this));
}
public bool IsValid
{
get;
private set;
}
}
还有一件事需要 - 在添加验证规则时键入安全性。否则每个子类都必须做那些看起来很尴尬的转换。理想情况下Func<T, bool>
会起作用,但是存在一大堆问题:我们不能从任何类型的HierarchyBase
继承我们的IValidatable<HierarchyBase>
,因为继承层次结构可以是N级深度(是的,我也感受到了这种气味;在Func<HierarchyBaseInheritor, bool>
中存储任何具体rules
并遍历它们。
你会如何介绍类型安全?
答案 0 :(得分:3)
正确的方法是让层次结构中的每个类负责验证自身:
HierarchyBase:
class HierarchyBase
{
public int A { get; set; }
public bool Validate()
{
return this.OnValidate();
}
protected virtual bool OnValidate()
{
return (this.A % 2 == 0);
}
}
HierarchyBaseInheritorA:
class HierarchyBaseInheritorA : HierarchyBase
{
public int B { get; set; }
protected override bool OnValidate()
{
return base.OnValidate() &&
(this.A > 10) &&
(this.B != 0);
}
}
HierarchyBaseInheritorB:
class HierarchyBaseInheritorB : HierarchyBaseInheritorA
{
public int C { get; set; }
protected override bool OnValidate()
{
return base.OnValidate() &&
(this.A < 20) &&
(this.B > 0) &&
(this.C == 0);
}
}
用法:
var result = new HierarchyBaseInheritorB();
result.A = 12;
result.B = 42;
result.C = 0;
bool valid = result.Validate(); // == true
答案 1 :(得分:3)
注意:以下解决方案是我和Eric Lippert之间的一个笑话。它有效,但可能不推荐。
我们的想法是定义一个引用“当前”类型的泛型类型参数(如this
引用“当前”对象)。
HierarchyBase:
class HierarchyBase<T>
where T : HierarchyBase<T>
{
protected readonly List<Func<T, bool>> validators;
public HierarchyBase()
{
validators = new List<Func<T, bool>>();
validators.Add(x => x.A % 2 == 0);
}
public int A { get; set; }
public bool Validate()
{
return validators.All(validator => validator((T)this));
}
}
HierarchyBaseInheritorA:
class HierarchyBaseInheritorA<T> : HierarchyBase<T>
where T : HierarchyBaseInheritorA<T>
{
public HierarchyBaseInheritorA()
{
validators.Add(x => x.A > 10);
validators.Add(x => x.B != 0);
}
public int B { get; set; }
}
HierarchyBaseInheritorB:
class HierarchyBaseInheritorB : HierarchyBaseInheritorA<HierarchyBaseInheritorB>
{
public HierarchyBaseInheritorB()
{
validators.Add(x => x.A < 20);
validators.Add(x => x.B > 0);
validators.Add(x => x.C == 0);
}
public int C { get; set; }
}
用法:
var result = new HierarchyBaseInheritorB();
result.A = 12;
result.B = 42;
result.C = 0;
bool valid = result.Validate(); // == true