我正试图在Autofac中实现一些关于注册多个事物的语法糖,但我被卡住了,我不知道这是否有一些设计模式名称可以搜索一些信息。
我在我的主要项目中有这样的东西:
protected override void Load(ContainerBuilder builder)
{
var busBuilder =
new BusBuilder()
.RegisterHandler<EventOne, DomainEventHandlerAdapter<EventOne>>()
.RegisterHandler<EventTwo, DomainEventHandlerAdapter<EventTwo>>()
.RegisterHandler<EventThree, DomainEventHandlerAdapter<EventThree>>();
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
我想重构它,因为我不希望我的主项目依赖于特定的NuGet包(Enexure Microbus包(。所以我想在我的主要项目中有这样的东西:
protected override void Load(ContainerBuilder builder)
{
builder.RegisterMyMicrobus(eventOptions => {
eventOptions
.RegisterDomainHandler<EventOne>()
.RegisterDomainHandler<EventTwo>()
.RegisterDomainHandler<EventThree>();
});
}
因此,我的主要项目对BusBuilder、DomainEventHandlerAdapter或RegisterMicroBus一无所知,也不依赖于该特定技术(Enexure Microbus(。所有的Autofac注册都将由我的另一个项目处理,这是唯一一个依赖特定技术的项目。
以下是我迄今为止在另一个项目上所做的工作:
我在Autofac的ContainerBuilder上创建了一个扩展方法,我将在其中传递eventOptions,它将是一个委托(lambda表达式(Action<EventOption>
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
if (eventOptions != null)
{
// TODO, how to implement EventOption and the chain registration?
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
任何链接或帮助都将不胜感激。这个模式必须有一个名称,但不知道它是如何调用的,而且我没有实现链方法的经验。
更新1:根据Erndob的建议,我查看了BusBuilder。但我又一次陷入了困境。
我创建了EventOption如下:
public class EventOption
{
public IReadOnlyList<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
private readonly List<IDomainEvent> _domainEvents= new List<IDomainEvent>();
public EventOption RegisterDomainHandler(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
return this;
}
}
但现在问题出在扩展方法上,因为我可以检索事件列表
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
// use busBuilder to register each one of the domain events in options
var eventOption = new EventOption();
eventOptions?.Invoke(eventOption);
foreach (var domainEvent in eventOption.DomainEvents)
{
var eventType = domainEvent.GetType();
// HERE is the problem. How to RegisterHandler using this generic method?
busBuilder
.RegisterHandler<eventType, DomainEventHandlerAdapter<eventType>>();
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
它不会编译,因为我试图将变量用作类型(RegisterHandler是泛型(。我找不到将变量转换为满足该调用的类型的方法。有什么想法或不同的方式来实现同样的目标吗?再次感谢
更新2:我已经改变了方法,它似乎可以工作。它编译并注册所有内容,但我必须进一步测试。
我已修改EventOption以存储类型:
public class EventOption
{
public IReadOnlyList<Type> Types => _types.AsReadOnly();
private readonly List<Type> _types = new List<Type>();
public DomainCommandOptions RegisterCommandHandler<TDomainCommand>()
where TDomainCommand : IDomainCommand
{
var domainCommandType = typeof(TDomainCommand);
_types.Add(domainCommandType);
return this;
}
}
然后扩展方法现在不同了,因为它在类型上进行迭代,并在运行时创建一个泛型类型。我发现Microbus有一个HandlerRegistration,我可以直接使用。
public static void RegisterMyMicrobus(this ContainerBuilder builder, Action<EventOption> eventOptions = null)
{
var busBuilder = new BusBuilder();
// use busBuilder to register each one of the domain events in options
var eventOption = new EventOption();
eventOptions?.Invoke(eventOption);
foreach (var type in eventOption.Types)
{
var handlerRegistration = new HandlerRegistration(type, typeof(DomainEventHandlerAdapter<>).MakeGenericType(type));
busBuilder.RegisterMessage(handlerRegistration);
}
builder
.RegisterMicroBus(busBuilder);
builder
.RegisterType<MicroBusDomainEventBus>()
.As<IDomainEventBus>();
}
查看您正在使用的项目的源代码。BusBuilder,这个链接的东西,在它的名字中有一个模式名称。建设者。回购本身说:
MicroBus是的一个简单的进程中中介。净
因此MicroBus是一个中介。看看中介模式。
以下是BusBuilder.cs的外观:https://github.com/Lavinski/Enexure.MicroBus/blob/master/src/Enexure.MicroBus/BusBuilder.cs
建筑本身基本上是这样做的:
public BusBuilder RegisterHandler<TMessage, TMessageHandler>()
where TMessageHandler : IMessageHandler<TMessage, Unit>
{
registrations.Add(HandlerRegistration.New<TMessage, TMessageHandler>());
return this;
}
正如您所看到的,实例有一个注册列表,然后当您想要注册新的东西时,它只会添加到列表中,然后返回自己,让您可以链接新的注册。