MediatR 和 NInject 中的单个实例

single instance in MediatR and NInject

在我的应用程序(带 NInject 的 MVC)的 bootstrap 中,我将这两个请求绑定到我的服务:

  kernel.Bind <IRequestHandler<SaveItemrequest, int>>()
       .To<MyService>();
kernel.Bind <IRequestHandler<MyGetmessageRequest, List<string>>>()
       .To<MyService>();


        kernel.Bind<SingleInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.TryGet(t));
        kernel.Bind<MultiInstanceFactory>().ToMethod(ctx => t => ctx.Kernel.GetAll(t));
             kernel.Bind<IMediator>().To<Mediator>();

在服务中,我有

public int Handle(SaveItemrequest req){
    int id= _db.save(req.Item);
    this.messages.add("OK");
   return id;
}
public List<string> Handle(MyGetmessageRequest req){

   return this.messages;
}

但是由于 MediatR 创建了 MyService 的新实例,所以当我收到消息时列表是空的:

id=_mediatr.Send(_saveReq); //ok
msgs=mediatr.Send(_getMsgsreq); //always empty

有没有办法强制 MediatR 对每个请求使用相同的实例?

这是设计使然 - 您将违背 CQS 模式来尝试执行您的建议。命令查询分离。您的处理程序不应保持状态。

但是,您可以做的是拥有另一项服务,具有 'per request' 生命周期范围,其中包含该请求的消息列表。
这比真正的单身人士更合适 - 因为单身人士将拥有所有消息,用于所有请求(跨用户等......)

首先,围绕 List<string> 创建一个包装器,它看起来像这样:

public interface IMessageStore
{
    IEnumerable<string> GetMessages();
    void AddMessage(string message);
}

public class MessageStore : IMessageStore
{
    private List<string> _messages = new List<string>();

    public IEnumerable<string> GetMessages()
    {
        return _messages.ToList();
    }

    public void AddMessage(string message)
    {
        _messages.Add(message);
    }
}

然后,在NInject中配置为InRequestScope

kernel.Bind<IMessageStore>>().To<MessageStore>()
    .InRequestScope();

这将为请求保留 MessageStore 的实例。

在您的处理程序中,依赖于 IMessageStore

public class MyService : <IRequestHandler<SaveItemrequest, int>, IRequestHandler<MyGetmessageRequest, List<string>>
{
    public MyService(IMessageStore messageStore)
    {
        _messageStore = messageStore;
    }

    public int Handle(SaveItemrequest req)
    {
        int id= _db.save(req.Item);

        _messageStore.AddMessage("OK");

        return id;
    }

    public List<string> Handle(MyGetmessageRequest req){

       return _messageStore.GetMessages();
    }
}

我的做法与@Alex 提出的类似。我已经创建了一个 HandlerService 服务来实现上面的 Handle 函数,我在其中注入了 MyService 并具有 httpcontext 生命周期的范围:

kernel.Bind<IMyService>().To<MyService>().InScope(ctx => HttpContext.Current ?? StandardScopeCallbacks.Thread(ctx));;

我绑定

 kernel.Bind <IRequestHandler<SaveItemrequest, int>>()
       .To<HandlerService>();
kernel.Bind <IRequestHandler<MyGetmessageRequest, List<string>>>()
       .To<HandlerService>();

现在我的处理程序服务有一个对 MyService 的引用,它产生了 HttpRequest 的生命周期。 Handler Service 是为每个请求实例化的,但它使用的 MyService 引用不是,因此 Messages 集合被保留并可以在以后查询。 谢谢