我需要存储一组类型。
所有的类型都实现了相同的接口IHandler<T>
,其中T
是父类的一个参数。
在运行时,我会枚举处理程序列表并处理消息。每个处理程序都是由一个构建器创建的(仅在内部使用StructureMap)。该构建器公开了一个类似于以下方法的方法:
static void DoSomething<T>(Action<T> action)
{
}
当然,我只有一个
Type
,所以不能使用上述方法。我通过将底层接口作为泛型参数和具体类型作为参数来解决这个问题:
DoSomething<IHandler<T>>(handlerType, h =>
{
h.Handle(message);
});
在DoSomething
方法内,我可以获取一个handlerType
的实例,但需要将其强制转换为IHandler<T>
。
不知道是否有更好/更简洁的方法。
更新
回应一些评论。
该集合是ICollection<Type>
,而不是实例。消息处理程序是按需创建的,在不同的线程上,对于每批消息都是如此,因此预先创建处理程序或使用Lazy<T>
不是一个选项。
本质上,我正在尝试抽象掉一些直接引用StructureMap的部分。具体来说,DoSomething<T>
实际上是在执行操作之前(它的Handle
方法)使用嵌套容器创建处理程序。
更新2(解决方案)
我意识到可以通过存储Action<T>
的集合并使用工厂创建处理程序来更好地处理这个问题。以下是一个简单的示例:
public class SimpleProcessor<T> where T : IMessage
{
ICollection<Action<T>> handlers;
T message;
public SimpleProcessor(T message)
{
this.handlers = new List<Action<T>>();
this.message = message;
}
public void AddHandler(Action<T> handler)
{
handlers.Add(handler);
}
public void Process()
{
foreach (var handler in handlers)
{
handler(message);
}
}
}
使用方法:
var testMessage = new TestMessage { Message = "Foo" };
var simpleProcessor = new SimpleProcessor<TestMessage>(testMessage);
simpleProcessor.AddHandler(m => DoSomething<TestMessageHandler>(h => h.Handle(m)));
simpleProcessor.Process();
我对这个解决方案比较满意。