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

时间:2018-04-27 08:30:27

标签: c# generics autofac projection eventhandler

我是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();
    }
}

然后我有很多Projectors(事件处理程序),它们对他们订阅的事件做了不同的事情。

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中注册我的投影仪以便以类似的方式使用它?

提前致谢!

1 个答案:

答案 0 :(得分:0)

如果你只有两种类型的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核心,这篇文章https://stackoverflow.com/a/45698048/814735包含有关如何实现这种通用控制器的很好的解释。