3

我一开始就被一个看似非常简单的任务所困扰。我有一个类层次结构,每个类都可以在其中定义自己的验证规则。定义验证规则应该尽可能简单。这几乎是需要的:

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遍历它们。

您将如何在这里介绍类型安全?

4

2 回答 2

3

注意:以下解决方案是我和 Eric Lippert 之间的一个笑话。它有效,但可能不推荐。

这个想法是定义一个泛型类型参数,它引用“当前”类型(如this引用“当前”对象)。

层次结构:

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
于 2010-09-24T20:47:30.653 回答
3

正确的方法是让层次结构中的每个类都负责验证自己:

层次结构:

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
于 2010-09-24T20:44:26.633 回答