3

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

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

我目前正在试验一个进程内变体。与 MediatR 非常相似,INotification我们有一个标记界面与 MediatRIEvent 类似,INotificationHandler<in INotification>我们有一个IEventHandler<in IEvent>

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

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

在代码方面,我希望以下类的行为就像它使用 MediatR 接口一样。

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

有什么建议么?

4

1 回答 1

2

现在的情况

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

public class SampleEvent : IEvent
{
}

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

使事件与 MediatR 兼容

我们需要有 MediatR 识别的事件,这意味着它们需要实现INotification.

第一种方法是让你的IEvent接口实现INotification。这样做的好处是几乎没有代码更改,它使您所有当前和新事件都与 MediatR 兼容。可能不太好的事情是,您当前的IEventlive 实现的程序集需要依赖 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
{
}

接线处理程序

无论您在上一步中采用哪种方式,您现在都处于这样一种状态,即您拥有同时实现IEvent和的类INotification,并且您拥有实现 的处理程序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>将被注入其中。

于 2018-05-02T01:28:20.613 回答