如何解决ServiceStack:在手动调用服务时恢复管道吗?
作为this question的后续活动,我想了解如何改善手动调用服务的情况。这变得比我想要的要长,但是我觉得需要背景信息。
进行发布/订阅(广播)时,不使用Messaging API中的常规顺序和流,而是使用IRedisClient,IRedisSubscription:在收到发布/订阅消息时得到回调,
>_subscription.OnMessage = (channel,msg) =>
{
onMessageReceived(ParseJsonMsgToPoco(msg));
};
然后,动作onMessageReceived
将依次调用一个正常的.NET / C#事件,如下所示:
protected override void OnMessageReceived(MyRequest request)
{
OnMyEvent?.Invoke(this,new RequestEventArgs(request));
}
这可行,我得到了我的请求,但是,我希望将其简化为另一个流,即Messaging API中的流,这意味着请求可以进入Service
类中实施,并且所有常规样板和依赖项注入都像使用Messaging API一样进行。
因此,在事件处理程序中,我手动调用了服务:
private void Instance_OnMyEvent(object sender,RequestEventArgs e)
{
using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
myRequestService.Any(e.Request);
}
}
确实找到了MyRequestService,并调用了Any,并且依赖项注入适用于该服务。
问题1:
- 诸如
OnBeforeExecute
,OnAfterExecute
之类的方法不会被调用,除非我手动调用它们,如myRequestService.OnBeforeExecute(e)
等。流水线的哪些部分丢失了?可以通过一些简单的方法将其恢复,所以我不必手动依次调用它们吗?
问题2:
当我这样做时,我想我搞砸了DI系统:
using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
myRequestService.OnBeforeExecute(e.Request);
myRequestService.Any(e.Request);
myRequestService.OnAfterExecute(e.Request);
}
我看到的效果是,我向container.AddScoped
注册的注入依赖项没有作用域,但看起来是静态的。之所以会这样,是因为我在注入的类中有一个Guid,并且在这种情况下,对于每个请求,该Guid总是相同的。
container.AddScoped<IRedisCache,RedisCache>();
和OnBeforeExecute(在Service的后代中)就像:
public override void OnBeforeExecute(object requestDto)
{
base.OnBeforeExecute(requestDto);
IRedisCache cache = TryResolve<IRedisCache>();
cache?.SetGuid(Guid.NewGuid());
}
因此,IRedisCache Guid每次都应该有所不同,但事实并非如此。但是,当我从头到尾使用Messaging API时,此方法工作正常。看来,如果我在AppHostBase后代中调用TryResolve,则会忽略AddScoped,并将一个实例放置在容器中,然后再将其删除。
解决方法
管道的哪些部分丢失了?
request pipeline均未执行:
myRequestService.Any(e.Request);
从物理上讲,它仅调用Any
类的MyRequestService
C#方法,它不会(也不能)做任何其他事情。
在服务请求期间调用其他服务的推荐方法是使用Service Gateway。
但是,如果您想在HTTP请求之外调用服务,则可以使用RPC Gateway来执行不受信任的服务,因为它会调用完整的请求管道并将HTTP错误响应转换为类型化错误响应:>
HostContext.AppHost.RpcGateway.ExecuteAsync()
要在服务请求之外执行内部/受信任的服务,您可以使用ServiceStack MQ使用的HostContext.AppHost.ExecuteMessage,它应用消息请求请求/响应筛选器,服务操作筛选器和事件。
我已向container.AddScoped注册
请勿使用Request Scoped dependencies outside of a HTTP Request,如果依赖项是ThreadSafe,请使用Singleton,否则将其注册为Transient。如果您需要传递每个请求的存储空间,请将它们传递到IRequest.Items
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。