ServiceStack:手动调用服务时恢复管道?
ServiceStack: Reinstate pipeline when invoking a Service manually?
作为 的后续,我想了解如何改进手动调用服务。这比我想要的要长,但我觉得需要背景信息。
在执行 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
class 实现,并且所有正常的样板和依赖项注入都像使用 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
中注册的注入依赖项没有作用域,但看起来是静态的。我看到这个是因为我在注入的 class 中有一个 Guid,并且在这种情况下该 Guid 始终相同,而对于每个请求它应该不同。
container.AddScoped<IRedisCache, RedisCache>();
OnBeforeExecute(在服务的后代中)就像:
public override void OnBeforeExecute(object requestDto)
{
base.OnBeforeExecute(requestDto);
IRedisCache cache = TryResolve<IRedisCache>();
cache?.SetGuid(Guid.NewGuid());
}
因此,IRedisCache Guid 每次都应该不同,但事实并非如此。然而,当我“从头到尾”使用 Messaging API 时,这很好用。似乎如果我在 AppHostBase 后代中调用 TryResolve,则 AddScoped 将被忽略,并将一个实例放入容器中,然后永远不会删除。
What parts of the pipeline is lost?
None的request pipeline被执行:
myRequestService.Any(e.Request);
实际上只是调用 MyRequestService
class 的 Any
C# 方法,它不会(也不能)做任何其他事情。
在服务请求期间调用其他服务的推荐方法是使用 Service Gateway.
但是如果您想在 HTTP 请求之外调用服务,您可以使用 RPC Gateway 来执行 non-trusted 服务,因为它会调用完整的请求管道并将 HTTP 错误响应转换为类型化错误回应:
HostContext.AppHost.RpcGateway.ExecuteAsync()
要在服务请求之外执行 internal/trusted 服务,您可以使用 HostContext.AppHost.ExecuteMessage ServiceStack MQ 使用的应用消息请求 Request/Response 过滤器、服务操作过滤器和事件。
I have registered with container.AddScoped
不要使用Request Scoped dependencies outside of a HTTP Request,如果依赖项是ThreadSafe,则使用Singleton,否则将它们注册为Transient。如果您需要传递 per-request 存储,请将它们传递给 IRequest.Items
.
作为
在执行 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
class 实现,并且所有正常的样板和依赖项注入都像使用 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
中注册的注入依赖项没有作用域,但看起来是静态的。我看到这个是因为我在注入的 class 中有一个 Guid,并且在这种情况下该 Guid 始终相同,而对于每个请求它应该不同。
container.AddScoped<IRedisCache, RedisCache>();
OnBeforeExecute(在服务的后代中)就像:
public override void OnBeforeExecute(object requestDto)
{
base.OnBeforeExecute(requestDto);
IRedisCache cache = TryResolve<IRedisCache>();
cache?.SetGuid(Guid.NewGuid());
}
因此,IRedisCache Guid 每次都应该不同,但事实并非如此。然而,当我“从头到尾”使用 Messaging API 时,这很好用。似乎如果我在 AppHostBase 后代中调用 TryResolve,则 AddScoped 将被忽略,并将一个实例放入容器中,然后永远不会删除。
What parts of the pipeline is lost?
None的request pipeline被执行:
myRequestService.Any(e.Request);
实际上只是调用 MyRequestService
class 的 Any
C# 方法,它不会(也不能)做任何其他事情。
在服务请求期间调用其他服务的推荐方法是使用 Service Gateway.
但是如果您想在 HTTP 请求之外调用服务,您可以使用 RPC Gateway 来执行 non-trusted 服务,因为它会调用完整的请求管道并将 HTTP 错误响应转换为类型化错误回应:
HostContext.AppHost.RpcGateway.ExecuteAsync()
要在服务请求之外执行 internal/trusted 服务,您可以使用 HostContext.AppHost.ExecuteMessage ServiceStack MQ 使用的应用消息请求 Request/Response 过滤器、服务操作过滤器和事件。
I have registered with container.AddScoped
不要使用Request Scoped dependencies outside of a HTTP Request,如果依赖项是ThreadSafe,则使用Singleton,否则将它们注册为Transient。如果您需要传递 per-request 存储,请将它们传递给 IRequest.Items
.