ServiceStack:手动调用服务时恢复管道? [英] ServiceStack: Reinstate pipeline when invoking a Service manually?

查看:27
本文介绍了ServiceStack:手动调用服务时恢复管道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为这个问题的后续,我想了解如何改进手动调用服务.这比我想要的要长,但我觉得需要背景信息.

As a follow-up to this question, I wanted to understand how my invoking of a Service manually can be improved. This became longer than I wanted, but I feel the background info is needed.

在进行发布/订阅(广播)时,没有使用 Messaging API 中的正常顺序和流程,而是在收到发布/订阅消息时收到回调,使用 IRedisClient、IRedisSubscription:

When doing a pub/sub (broadcast), the normal sequence and flow in the Messaging API isn't used, and I instead get a callback when a pub/sub message is received, using IRedisClient, IRedisSubscription:

_subscription.OnMessage = (channel, msg) =>
{
    onMessageReceived(ParseJsonMsgToPoco(msg));
};

Action onMessageReceived 将依次调用一个普通的 .NET/C# 事件,如下所示:

The Action onMessageReceived will then, in turn, invoke a normal .NET/C# Event, like so:

protected override void OnMessageReceived(MyRequest request)
{
    OnMyEvent?.Invoke(this, new RequestEventArgs(request));
}

这有效,我收到了我的请求以及所有这些,但是,我希望将其简化为另一个流程,即消息传递 API 中的流程,这意味着该请求会进入服务 类实现,并且所有正常的样板文件和依赖项注入都会像使用 Messaging API 一样发生.

This works, I get my request and all that, however, I would like it to be streamlined into the other flow, the flow in the Messaging API, meaning, the request finds its way into a Service class implementation, and that all normal boilerplate and dependency injection takes place as it would have using Messaging API.

因此,在我的事件处理程序中,我手动调用了服务:

So, in my Event handler, I manually invoke the Service:

private void Instance_OnMyEvent(object sender, RequestEventArgs e)
{
    using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
    {
        myRequestService.Any(e.Request);
    }
}

并且确实找到了 MyRequestService 并调用了 Any,并且依赖注入适用于该服务.

and the MyRequestService is indeed found and Any called, and dependency injection works for the Service.

问题 1:

  • OnBeforeExecuteOnAfterExecute 等方法不会被调用,除非我手动调用它们,例如:myRequestService.OnBeforeExecute(e)等等.管道的哪些部分丢失了?能否以某种简单的方式恢复它,这样我就不必按顺序手动调用它们中的每一个?
  • Methods such as OnBeforeExecute, OnAfterExecute etc, are not called, unless I manually call them, like: myRequestService.OnBeforeExecute(e) etc. What parts of the pipeline is lost? Can it be reinstated in some easy way, so I don't have to call each of them, in order, manually?

问题 2:

当我这样做时,我认为我搞砸了 DI 系统:

I think I am messing up the DI system when I do this:

using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
{
    myRequestService.OnBeforeExecute(e.Request);
    myRequestService.Any(e.Request);
    myRequestService.OnAfterExecute(e.Request);
}

我看到的效果是,我已向 container.AddScoped 注册的注入依赖项没有作用域,但似乎是静态的.我看到这一点是因为我在注入的类中有一个 Guid,并且在这种情况下 Guid 总是相同的,每个请求都应该不同.

The effect I see is that the injected dependencies that I have registered with container.AddScoped, isn't scoped, but seems static. I see this because I have a Guid inside the injected class, and that Guid is always the same in this case, when it should be different for each request.

container.AddScoped<IRedisCache, RedisCache>();

和 OnBeforeExecute(在 Service 的后代中)就像:

and the OnBeforeExecute (in a descendant to Service) is like:

public override void OnBeforeExecute(object requestDto)
{
    base.OnBeforeExecute(requestDto);
    IRedisCache cache = TryResolve<IRedisCache>();
    cache?.SetGuid(Guid.NewGuid());
}

因此,IRedisCache Guid 每次都应该不同,但事实并非如此.但是,当我从头到尾"使用 Messaging API 时,这很好用.看来如果我调用AppHostBase后代中的TryResolve,则忽略了AddScoped,在容器中放置了一个实例,然后再也不移除.

So, the IRedisCache Guid should be different each time, but it isn't. This however works fine when I use the Messaging API "from start to finish". It seems that if I call the TryResolve in the AppHostBase descendant, the AddScoped is ignored, and an instance is placed in the container, and then never removed.

推荐答案

管道的哪些部分丢失了?

What parts of the pipeline is lost?

请求管道均未执行:

myRequestService.Any(e.Request);

仅在物理上调用 MyRequestService 类的 Any C# 方法,它不会(也不能)执行任何其他操作.

Is physically only invoking the Any C# method of your MyRequestService class, it doesn't (nor cannot) do anything else.

在服务请求期间调用其他服务的推荐方式是使用服务网关.

The recommended way for invoking other Services during a Service Request is to use the Service Gateway.

但是如果您想在 HTTP 请求之外调用服务,您可以使用 RPC 网关用于在调用完整的请求管道时执行不受信任的服务将 HTTP 错误响应转换为类型化错误响应:

But if you want to invoke a Service outside of a HTTP Request you can use the RPC Gateway for executing non-trusted services as it invokes the full Request Pipeline & converts HTTP Error responses into Typed Error Responses:

HostContext.AppHost.RpcGateway.ExecuteAsync()

要在服务请求之外执行内部/受信任的服务,您可以使用 HostContext.AppHost.ExecuteMessage 由 ServiceStack MQ 使用,它应用消息请求请求/响应过滤器、服务操作过滤器和;活动.

For executing internal/trusted Services outside of a Service Request you can use HostContext.AppHost.ExecuteMessage as used by ServiceStack MQ which applies Message Request Request/Response Filters, Service Action Filters & Events.

我已经注册了 container.AddScoped

I have registered with container.AddScoped

不要使用请求范围之外的依赖HTTP 请求,如果依赖项是 ThreadSafe 则使用 Singleton,否则将它们注册为 Transient.如果您需要传递每个请求的存储,请在 IRequest.Items 中传递它们.

Do not use Request Scoped dependencies outside of a HTTP Request, use Singleton if the dependencies are ThreadSafe, otherwise register them as Transient. If you need to pass per-request storage pass them in IRequest.Items.

这篇关于ServiceStack:手动调用服务时恢复管道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆