Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以泛型类型安全的方式验证层次结构中的类?_C#_Oop_Inheritance_Type Safety - Fatal编程技术网

C# 如何以泛型类型安全的方式验证层次结构中的类?

C# 如何以泛型类型安全的方式验证层次结构中的类?,c#,oop,inheritance,type-safety,C#,Oop,Inheritance,Type Safety,我一开始就被一项看起来很简单的任务困住了。我有一个类层次结构,每个类都可以定义自己的验证规则。定义验证规则应该尽可能简单。以下是我们所需要的: class HierarchyBase { private List<Func<object, bool>> rules = new List<Func<object, bool>>(); public int fieldA = 0; public HierarchyBase()

我一开始就被一项看起来很简单的任务困住了。我有一个类层次结构,每个类都可以定义自己的验证规则。定义验证规则应该尽可能简单。以下是我们所需要的:

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;
    }
}
类层次结构库
{
私有列表规则=新列表();
公共int fieldA=0;
公共层次结构库()
{
AddRule(x=>((HierarchyBase)x).fieldA%2==0);
}
受保护的虚拟无效操作()
{
fieldA++;
}
受保护的无效添加规则(Func validCriterion)
{
规则。添加(有效标准);
}
公共行政运作
{
操作();
验证();
}
受保护的虚拟无效操作()
{
fieldA++;
}
私有void Validate()
{
IsValid=rules.All(x=>x(this));
}
公共布尔是有效的
{
得到;
私人设置;
}
}
在添加验证规则时,还需要一件事——类型安全。否则,每个子类将不得不进行那些看起来很尴尬的造型。理想情况下,
Func
会起作用,但这有一大堆问题:我们不能从任何类型的
IValidatable
继承我们的
HierarchyBase
,因为继承层次可以是N个层次(是的,我也能感觉到味道);将任何具体的
Func
存储在
规则中并遍历它们


您将如何在这里引入类型安全性?

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

等级库:

层次结构:

层次结构:


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

其思想是定义一个泛型类型参数,该参数引用“当前”类型(比如
这个
引用“当前”对象)

等级库:


我不确定我是否理解这个问题,引入泛型并将
Func
HierarchyBase
?+1一起使用有什么不对。使用lambdas在这里没有任何好处;AddRule方法受保护,因此无法从外部注入规则集。这些规则不是类不变量,验证规则可能非常复杂。lambda只是为了简单起见,可以用ValidationRule对象代替。我们不会通过分离规则来将不同的职责与这些类混合在一起。这不是“让层次结构中的每个类负责自身验证”,而是“让层次结构中的每个类负责定义其验证规则”@dbt:在经典OOP中,要么是此继承,要么是带有e.Cancel的事件。我只是觉得OP试图得到更多的“声明性”解决方案,而不是“功能性”解决方案。啊,顺便说一句,我喜欢你基于的答案:)基思:不难想象验证规则是从数据库或XML文件加载的。我有这个解决方案,但我甚至不想注意到:)
class HierarchyBase
{
    public int A { get; set; }

    public bool Validate()
    {
        return this.OnValidate();
    }

    protected virtual bool OnValidate()
    {
        return (this.A % 2 == 0);
    }
}
class HierarchyBaseInheritorA : HierarchyBase
{
    public int B { get; set; }

    protected override bool OnValidate()
    {
        return base.OnValidate() &&
               (this.A > 10) &&
               (this.B != 0);
    }
}
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
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));
    }
}
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; }
}
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