动态泛型接口强制转换



我想动态地发现和注册接口实现。为了便于讨论,我有两个类似的方法:

public void Register<TEvent>(IHandler<TEvent> handler) where TEvent : IEvent
public void Register<TEvent>(Action<TEvent> action) where TEvent : IEvent
{
    Register<TEvent>(handler.Handle);
}

接口如下:

public interface IHandler<T> where T : IEvent
{
    void Handle(T args);
}
public interface IEvent
{
}

然后我有具体的实现,如:

public class ChangedEvent : IEvent
{...}
public class ChangedHandler : IHandler<ChangedEvent>
{
    public void Handle(ChangedEvent args)
    {
    }
}

我可以在我的程序集中发现IHandler<>的所有具体实现,我想做这样的事情:

IList<Type> types = TypeFinder.GetImplementors(typeof(IHandler<>));
foreach (Type type in types)
{
    object instance = Activator.CreateInstance(type);
    Listeners.Register((IHandler<IEvent>)instance);
}

代码可以编译,它不是无效的,但是在运行时强制转换失败,因为它是无效的。但是,如果我转换为一个具体的事件,比如:

IList<Type> types = TypeFinder.GetImplementors(typeof(IHandler<>));
foreach (Type type in types)
{
    object instance = Activator.CreateInstance(type);
    Listeners.Register((IHandler<ChangedEvent>)instance);
}

此强制转换是有效的,并且将运行。问题是场景的动态性,我希望能够发现类型并注册它们。我不想为处理程序创建非泛型接口,但我认为这是一个不可能的场景,因为框架没有足够的信息来推断所需的类型。有什么方法可以做到这一点,或者你有什么建议来达到预期的结果吗?

许多谢谢。

由于协方差和逆变性的原因,这不起作用,想象它起作用了,并且您做了以下操作。

public class AnotherTypeOfEvent : IEvent      {...} 
public void Register<TEvent>(IHandler<TEvent> handler) where TEvent : IEvent 
{
    //Really our runtime type expects ChangedEvent, but our constraint is
    //only for IEvent so you could do this - oh dear..
    handler.Handle(new AnotherTypeOfEvent());     
}
Listeners.Register((IHandler<IEvent>)new ChangedHandler());   

您将把AnotherTypeOfEvent传递到您的ChangedHandler.Handle方法中,该方法显然期望ChangedEvent,这将导致各种问题。

为什么不在typefinder中指定您想要获得的类型,因为您将在之后强制转换它?

IList<Type> types = TypeFinder.GetImplementors(typeof(IHandler<IEvent>));
foreach (Type type in types)
{
    object instance = Activator.CreateInstance(type);
    Listeners.Register((IHandler<IEvent>)instance);
}

我不知道你得到了什么错误。我可以很好地编译:

public interface IEvent
{
}
public interface IHandler<T>
{
}
public class Test //: ITest
{
    public void Register<TEvent>(IHandler<TEvent> handler) where TEvent : IEvent
    {
    }
}
public class ChangedEvent : IEvent
{

}
public class Example
{
    public static void Main()
    {
        Test t = new Test();
        Type[] types = new Type[10];
        foreach (Type type in types)
        {
            object instance = Activator.CreateInstance(type);
            t.Register((IHandler<IEvent>)instance);
        }
    }
}

相关内容

  • 没有找到相关文章

最新更新