在现有框架中调整/包裹MediatR通知

时间:2018-03-31 09:56:43

标签: c# autofac mediatr

TL; DR如何调整现有的一组事件/通知和相关处理程序,以便MediatR可以使用它们,而无需为每个现有类型实现额外的处理程序和通知?

长版: 我们目前有一个调度事件的系统,我们使用总线实现来进行实际的传输。

我目前正在尝试使用进程内变体。 与MediatR INotification类似,我们有一个标记界面IEvent 同样类似于MediatR的INotificationHandler<in INotification>,我们有一个IEventHandler<in IEvent>

我们使用Autofac来注册我们的EventHandlers,然后我们在实际消耗总线上的东西时会有一些反思。

我想做的,但无法理解,是实现某种通用适配器/包装器,以便我可以保留现有的事件和事件处理程序,并在从MediatR发送通知时使用它们,基本上减少了我现有代码的变化量围绕设置容器。

就代码而言,我希望以下类的行为就像使用MediatR接口一样。

public class MyHandler : IEventHandler<SampleEvent>
{
    public Task Handle(SampleEvent input) => Task.CompletedTask;
}

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

现状

现在你的代码看起来像这样:

public class SampleEvent : IEvent
{
}

public class SampleEventHandler : IEventHandler<SampleEvent>
{
    public Task Handle(SampleEvent input) => Task.CompletedTask;
}

使事件与MediatR

兼容

我们需要有MediatR识别的事件,这意味着他们需要实施INotification

执行此操作的第一种方法是使IEvent接口实现INotification。关于这一点的好处是代码变化非常小,它使您所有的当前和新事件与MediatR兼容。可能不那么伟大的事情是,当前IEvent实现的程序集需要依赖于MediatR。

public interface IEvent : INotification
{
}

如果这不可行,我认为这样做的第二种方法是创建新的,特定于MediatR的类,这些类继承现有的类并实现INotification。这意味着您需要为每个现有类创建一个适配器类,但是您可以从MediatR依赖项中释放现有项目。

// Lives in AssemblyA
public class ExistingEvent : IEvent
{
}

// Lives in AssemblyB that has a dependency on both
// AssemblyA and MediatR
public class MediatrExistingEvent : ExistingEvent, INotification
{
}

连接处理程序

无论您在上一步中采用哪种方式,现在都处于这样一种状态,即您拥有同时实现IEventINotification的类,并且您拥有实现IEventHandler<in T> where T : IEvent的处理程序}。

我们可以创建一个满足MediatR API的适配器类,并将工作委托给现有的处理程序:

public class MediatrAdapterHandler<T> : INotificationHandler<T>
    where T : IEvent, INotification
{
    private readonly IEventHandler<T> _inner;

    public MediatrAdapterHandler(IEventHandler<T> inner)
    {
        _inner = inner;
    }

    public Task Handle(T notification) => _inner.Handle(notification);
}

最后一件事是在Autofac容器中注册这个类。鉴于您现有的处理程序已注册为IEventHandler<T>,它很容易完成:

builder
    .RegisterGeneric(typeof(MediatrAdapterHandler<>))
    .As(typeof(INotificationHandler<>));

每当您向容器询问INotificationHandler<T>的实例时,它将创建MediatrAdapterHandler<T>的实例,其中将注入IEventHandler<T>的原始实现。