C#:转换为具有基类型的泛型接口 [英] C#: cast to generic interface with base type

查看:22
本文介绍了C#:转换为具有基类型的泛型接口的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

代码如下:

public interface IValidator<T>
{
   bool IsValid(T obj);
}

public class OrderValidator: IValidator<Order>
{
  // ...
}

public class BaseEntity
{
}

public class Order: BaseEntity
{
}

问题是我做不到:

var validator = new OrderValidator();
// this line throws because type can't be converted
var baseValidator = (IValidator<BaseEntity>)validator;
// all this is because I need a list with IValidator<Order>, IValidator<BaseOrder>, etc.
IList<IValidator<BaseEntity>> allValidators = ... 

如何获取和存储 IValidator 的所有实现的列表?对于基础 T - 比如说,BaseEntity?目前我做的非通用 IValidator 接受对象 obj",但它不好,也不是类型安全的.

How do I get and store a list of all implementations of IValidator<T> for base T - say, BaseEntity? Currently I do non-generic IValidator that accepts "object obj" but it is not good and not type-safe.

有趣的是,C#允许编译:

var test = (IValidator<BaseEntity>)new OrderValidator();

但在运行时失败

   Unable to cast object of type 'OrderValidator' to type 'IValidator`1[Orders.Core.BaseEntity]'

这与 Windsor 给我的异常相同(我尝试了 Windsor 和手动类型查找,这个问题确实与此无关,仅与接口转换有关).

This is the same exception that Windsor gives me (I tried both Windsor and manual types lookup, this issue is really not related to this, only to the interfaces casting).

感谢 Heinzi,我现在明白为什么我不能转换了 - 因为 IValidator for Order 期望 Order 作为泛型类型.但是如何返回不同类型的 IValidator 列表?原因是 BaseEntity 获取其真实类型并收集所有验证器 - 对于从 GetType() 到对象的所有类型.我真的很想拥有一个通用的 GetValidators() 然后对其进行操作.

Thanks to Heinzi, I see now why I can't cast - because IValidator for Order expects Order as generic type. But how do I return a list of IValidator for different types? The reason is that the BaseEntity takes its real type and gathers all validators - for all types from GetType() to the object. I'd really like to have a generic GetValidators() and then operate on it.

推荐答案

如果我解释一下为什么禁止强制转换可能对你有帮助:假设你有以下功能

Maybe it helps you if I explain why this cast is forbidden: Assume that you have the following function

void myFunc(IValidator<BaseEntity> myValidator) {
    myValidator.IsValid(new BaseEntity());
}

此代码将正确编译.然而,如果您将 OrderValidator 传递给该函数,您将得到一个运行时异常,因为 OrderValidator.IsValid 需要一个 Order,而不是一个 BaseEntity.如果允许您的演员表,类型安全将不再得到维护.

This code would compile correctly. Nevertheless, if you passed an OrderValidator to this function, you would get a run-time exception, because OrderValidator.IsValid expects an Order, not a BaseEntity. Type safety would no longer be maintained if your cast were allowed.

C# 4 允许 通用协变和逆变,但这对您的情况没有帮助,因为您使用 T 作为 input 参数.因此,只有转换为 IValidator 才能以类型安全的方式完成.

C# 4 allows for generic co- and contravariance, but this would not help in your case, since you use T as an input parameter. Thus, only casting to an IValidator<SomeSubtypeOfOrder> could be done in a type-safe way.

所以,要明确的是,您不能将 OrderValidator 转换为 IValidator,因为您的 OrderValidator 只能验证订单,而不能验证所有类型的 BaseEntities.然而,这正是 IValidator 所期望的.

So, to be clear, you cannot cast OrderValidator to IValidator<BaseEntity> because your OrderValidator can only validate orders, not all kinds of BaseEntities. This, however, is what would be expected of an IValidator<BaseEntity>.

这篇关于C#:转换为具有基类型的泛型接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆