我想动态发现并注册接口实现。为了论证,我有两种类似的方法:
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);
}
此演员表有效,并且会运行。问题是场景的动态,我希望能够发现类型并注册它们。 我不想为处理程序创建非泛型接口,但我认为这是一个不可能的场景,因为框架没有足够的信息来推断所需的类型。 有没有办法实现这个目标,或者你有任何消化方法可以达到预期的效果吗?
非常感谢。
答案 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);
}
}
}