ServiceStack:手动调用服务时恢复管道?

2024-03-31

作为后续这个问题 https://stackoverflow.com/questions/64560997/servicestack-messaging-api-can-it-make-a-broadcast,我想了解如何改进我对服务的手动调用。这比我想要的要长,但我觉得需要背景信息。

在执行 pub/sub(广播)时,不使用消息 API 中的正常顺序和流程,而是在收到 pub/sub 消息时使用 IRedisClient、IRedisSubscription 获得回调:

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

那个行动onMessageReceived然后,将依次调用普通的 .NET/C# 事件,如下所示:

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

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

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

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

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

问题一:

  • 方法如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 始终相同,而每个请求的 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,并将一个实例放置在容器中,然后永远不会删除。


管道的哪些部分丢失了?

没有任何一个请求管道 https://docs.servicestack.net/order-of-operations被执行:

myRequestService.Any(e.Request);

仅在物理上调用Any你的C#方法MyRequestService类,它不(也不不能)做任何其他事情。

在服务请求期间调用其他服务的推荐方法是使用服务网关 https://docs.servicestack.net/service-gateway.

但是如果您想在 HTTP 请求之外调用服务,您可以使用RPC网关 https://docs.servicestack.net/order-of-operations#rpcgateway用于执行不可信服务,因为它调用完整的请求管道并将 HTTP 错误响应转换为类型化错误响应:

HostContext.AppHost.RpcGateway.ExecuteAsync()

要在服务请求之外执行内部/可信服务,您可以使用HostContext.AppHost.ExecuteMessage https://docs.servicestack.net/order-of-operations#mq-non-http-custom-hooks由 ServiceStack MQ 使用,它应用消息请求请求/响应过滤器、服务操作过滤器和事件。

我已经注册了container.AddScoped

不使用HTTP 请求之外的请求范围依赖项 https://forums.servicestack.net/t/hostcontext-resolveservice-idisposable/7809/2?u=mythz,如果依赖项是ThreadSafe,则使用Singleton,否则将它们注册为Transient。如果您需要传递每个请求的存储,请传递它们IRequest.Items.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ServiceStack:手动调用服务时恢复管道? 的相关文章

随机推荐