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 集合被保留并可以在以后查询。
谢谢
在我的应用程序(带 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 集合被保留并可以在以后查询。 谢谢