动态通用接口转换

时间:2011-04-08 09:09:19

标签: c# generics reflection casting

我想动态发现并注册接口实现。为了论证,我有两种类似的方法:

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&lt;&gt;的所有具体实现在我的集会中,我想做这样的事情:

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

代码将编译,它不是无效的,但在运行时,强制转换失败,因为它无效。 但是,如果我转向具体的IEvent,如:

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

此演员表有效,并且会运行。问题是场景的动态,我希望能够发现类型并注册它们。 我不想为处理程序创建非泛型接口,但我认为这是一个不可能的场景,因为框架没有足够的信息来推断所需的类型。 有没有办法实现这个目标,或者你有任何消化方法可以达到预期的效果吗?

非常感谢。

3 个答案:

答案 0 :(得分:1)

由于Covariance and contravariance,这不起作用,想象一下这种方法有效,你做了以下工作。

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,这会导致各种各样的问题。

答案 1 :(得分:0)

为什么不在typefinder中指定你想要获得的类型,因为你将在之后投射它?

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

答案 2 :(得分:-1)

我不确定你得到了什么错误。这对我来说很好:

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);
        }
    }
}