如何使用 Autofac 解决通用事件处理程序的不同实现

How to resolve different implementations of generic event handlers with Autofac

我是 Autofac 的新手,我无法获得事件订阅者应用程序工作的示例。你能帮我建模吗?

思路如下。

我有一个 REST API 控制器,客户端可以在其中 POST 事件(IDomainEvent 的实现)

控制器需要接收注入的所有投影仪 类(事件处理程序),它们将对事件执行某些操作。

public class EventsController 
    : Controller
{
    private readonly IEnumerable<IEventHandler> _projectors;

    public EventsController(IEnumerable<IEventHandler> projectors)
    {
        _projectors = projectors;
    }

    [HttpPost("EventA")]
    public IActionResult AddEventA([FromBody]EventA evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }

    [HttpPost("EventB")]
    public IActionResult AddEventB([FromBody]EventB evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }
}

然后我有许多投影仪(事件处理程序)对它们订阅的事件执行不同的操作。

public class ProjectorA : IEventHandler<EventA>, IEventHandler<EventB>
{
    private readonly IRepository _repository;

    public ProjectorA(IRepository repository)
    {
        _repository = repository;
    }

    public void Handle(EventA evt)
    {
        // do something with EventA
    }

    public void Handle(EventB evt)
    {
        // do something with EventB
    }
}

public class ProjectorB : IEventHandler<EventA>
{
    private readonly IRepository _repository;

    public ProjectorA(IRepository repository)
    {
        _repository = repository;
    }

    public void Handle(EventA evt)
    {
        // do something with EventA
    }

    // I don't care about EventB so I don't subscribe to it
}

我猜 IEventHandler 应该是这样的:

public interface IEventHandler<in TDomainEvent>
    : IEventHandler
    where TDomainEvent : IDomainEvent
{
    void Handle(TDomainEvent evt);
}

如何修改此模型以及如何在 Autofac 中注册我的投影仪以类似方式使用它?

提前致谢!

如果你只有 2 种类型的 Event 最简单的方法是有 2 种依赖关系

public class EventsController 
    : Controller
{
    private readonly IEnumerable<IEventHandler<EventA>> _Aprojectors;
    private readonly IEnumerable<IEventHandler<EventB>> _Bprojectors;

    public EventsController(IEnumerable<IEventHandler<EventA>> Aprojectors,
                            IEnumerable<IEventHandler<EventB>> Bprojectors)
    {
        _Aprojectors = Aprojectors;
        _Bprojectors = Bprojectors;
    }

    // ...
}

但是如果你想要一个通用的解决方案,最简单的方法是创建一个通用存储库

public class EventsController<TEvent> 
    : Controller
    where TEvent : IEvent 
{
    private readonly IEnumerable<IEventHandler<TEvent>> _projectors;

    public EventsController(IEnumerable<IEventHandler<Event>> projectors)
    {
        _projectors = projectors;
    }

    [HttpPost()]
    public IActionResult AddEvent([FromBody]TEvent evt)
    {
        foreach (var projector in _projectors)
        {
            projector.Handle(evt);
        }
        return Ok();
    }
}

并像这样声明你的 EventHandler

builder.RegisterType<ProjectorA>().As<IEventHandler<AEvent>>();
builder.RegisterType<ProjectorB>().As<IEventHandler<BEvent>>();

在 ASP.net MVC 中默认不实现通用控制器。对于 ASP.net 核心,这个 post 包含关于如何实现这样一个通用控制器的很好的解释。