1

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

  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 对每个请求使用相同的实例?

4

2 回答 2

1

这是设计使然 - 您正在违背 CQS 模式,试图按照您的建议进行操作。命令查询分离。您的处理程序不应该保持状态。

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

首先,围绕 a 创建一个包装器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();
    }
}
于 2017-11-09T16:46:42.720 回答
1

我以与@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>();

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

于 2017-11-10T17:10:08.863 回答