我试图理解为什么在这种情况下施法不起作用。
假设以下接口:
public interface IDomainEvent { }
public interface IHandler<T> where T: IDomainEvent
{
void Handle(T args);
}
这些简单的实现:
public class SomeEvent : IDomainEvent
{
public string Value { get; set; }
}
public class SomeEventHandler : IHandler<SomeEvent>
{
public void Handle(SomeEvent args) { }
}
我不明白为什么我不能做这个演员:
var handler = new SomeEventHandler() as IHandler<IDomainEvent>;
我正在使用Autofac来解析基于事件的处理程序列表,它做得很好,但它创建它们当然是完全具体的,在运行时我需要通过接口处理它们。我可以使用反射很容易调用handle方法,但看起来这应该可行:/
答案 0 :(得分:3)
您无法在概念上将IHandler<SomeEvent>
视为IHandler<IDomainEvent>
。 IHandler<IDomainEvent>
需要能够接受AThirdEvent
(实现IDomainEvent
)的实例作为Handle
的参数,但您的SomeEventHandler
类型不能接受AThirdEvent
个实例,只接受SomeEvent
个实例。
编译器正确地通知您,从概念的角度来看,此类型转换无效。
从概念上讲,您的界面实际上是逆变。如果您有IHandler<IDomainEvent>
,则可以将其隐式转换为IHandler<SomeEvent>
(如果您调整了接口的定义以通知编译器它实际上是逆变的),因为如果您的Handle
方法可以接受任何类型的IDomainEvent
然后显然它可以接受每一个SomeEvent
。
答案 1 :(得分:1)
这需要您的interface to be covariant。
public interface IHandler<out T> : where T : IDomainEvent
然而,您的界面本身并不支持这一点,因为它有效地逆转。允许此工作不是类型安全的,并且没有直接的解决方法。协变接口只允许返回T
,不接受T
作为方法的参数。
有关详细信息,请参阅variance in generic interfaces。