我想验证一个具有泛型类型属性的类:
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。
答案 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>
的使用不一致。我假设验证器是正确的,你的可验证对象上的属性是一个列表,但显然我不知道是否可以更改该列表等。