让我们假设这些类/接口:
public interface ICommand
{
}
public class SomeCommand : ICommand
{
}
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
void Handle(SomeCommand arg){ /* do something */ }
}
public interface ICommandBus
{
void RegisterHandler<T>(T t) where T : ICommandHandler<T>;
void RegisterHandlerByParam<T2>(ICommandHandler<T2> t2) where T2 : ICommand;
void RegisterHandlerMethod<T3>(Action<T3> action) where T3 : ICommand
}
public class TheCommandBus : ICommandBus
{
// implements ICommandBus ...
}
我想自动注册 ICommandHandler<> 的所有实现。所有变体(Register*)都是有效的解决方案,即使我更喜欢 Action 参数,因为它更灵活并且不依赖于 Handler 接口(只是动作委托)。
Autofac 能够根据程序集扫描注册类型并注册找到的通用接口的实现,例如:
builder.RegisterAssemblyTypes(Assembly.LoadFrom("MyAssembly.dll"))
.AsClosedTypesOf(typeof(ICommandHandler<>));
所以我已经注册了所有实现。现在我需要将它们全部自动注册到TheCommandBus。怎么做?
我可以通过添加这些行来手动执行此操作(例如在 OnActivated 期间):
builder.RegisterType<TheCommandBus>().As<ICommandBus>().OnActivated(args =>
{
// now I need to list all implementations here!!! please, no...
args.Instance.RegisterHandler<ICommandHandler<SomeCommand>>(args.Context.Resolve<ICommandHandler<SomeCommand>>());
// does not look better to me than before ...
args.Instance.RegisterHandlerByParam<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>())
// uses delegate for, but still need to list all variants
args.Instance.RegisterHandlerMethod<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>().Handle)
});
如果我想在注册期间在 lambda 表达式中使用这种类型,我会遇到问题,我需要识别具体类型,就像这个关于另一个组件激活过程的示例一样。但我不想手动列出所有这些...自动想要这样的东西。
如何捕获所有 ICommandHandler 实现并使用 Register* 方法自动注册它们?
编辑:
另一种变体是扩展 SomeCommandHandler 类以在其构造函数中解析时注册自身:
public SomeCommandHandler(ICommandBus commandBus)
{
// and register here, for example
commandBus.RegisterHandlerbyParam(this);
}
这样我必须向 AsClosedTypesOf 注册结果提供 AutoActivate() 。(一个可能的解决方案,但现在“处理者”有两个职责......注册和处理)