验证泛型类型的非泛型属性

时间:2017-01-16 08:59:06

标签: c# .net validation .net-core

我想验证一个具有泛型类型属性的类:

class Foo
{
   [ValidHistoryDate]
   public MyType<string> bar;
   [ValidHistoryDate]
   public MyType<int> baz;
   [ValidHistoryDate]
   public MyType<float> bat;
}
class MyType<T>
{
   public string date;
   public T property;
}

泛型类型还包含一个日期,属性(字符串),应根据有效日期进行验证,因此我编写了此函数来执行此操作:

public class ValidHistoryDateAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        if (value == null)
            return true;
        var v = (List<MyType<object>>)value;
        bool valid = true;
        foreach (var f in v)
        {
            if (!Regex.Match(f.Date, @"^[0-9]{2}\.[0-9]{2}\.[0-9]{4}$").Success)
                valid = false;
        }
        return valid;
    }
}

验证不关心属性“property”,但它应该关心字符串。 不幸的是演员阵容失败了:

        var v = (List<MyType<object>>)value;

我的意思是:当然是这样,因为“对象”不是真正的类型。我想对所有类型使用验证属性,在验证中我实际上甚至不关心“属性”。

有什么方法可以很好地解决这个问题吗?我不想为每种可能的类型添加ValidHistoryDateAttribute。

1 个答案:

答案 0 :(得分:3)

如果我这样做,我会在你的代码中添加一个非泛型基类型:

public class ValidatableObject
{
    public string date;
}

然后我的课程将是:

class MyType<T> : ValidatableObject
{
   public T property;
}

然后,您的验证代码将引用基类,使事情变得更加简单。

看起来你实际上正在尝试投射List<GenerericHistory<T>>类型的东西,这会遇到方差问题。如果您假设您正在使用我的基类,则传入的项目无法轻松转换为List<ValidatableObject> - 以查看为什么认为实际列表应该只允许添加GenerericHistory<T>(其中T是特定类型)对象,而List<ValidatableObject>将允许添加任何类型的GenerericHistory<T>个对象。因此不允许演员。

如果您要将列表更改为IEnumerable<GenerericHistory<T>>,则可以转换为IEnumerable<ValidatableObject>。原因是这次我们有一个readOnly对象,所以我们所做的就是找出ValidatableObject类型的对象,并且因为知道实际的类只会返回GenerericHistory<T>(对于特定的T)我们也知道它总是返回ValidatableObject类型,因此这次允许转换。

最后一点部分基于推测,因为您的代码似乎与代码中List<T>的使用不一致。我假设验证器是正确的,你的可验证对象上的属性是一个列表,但显然我不知道是否可以更改该列表等。