servicestack,publish-subscribe,Redis,servicestack,Publish Subscribe" /> servicestack,publish-subscribe,Redis,servicestack,Publish Subscribe" />

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

Redis ServiceStack:手动调用服务时恢复管道?,redis,servicestack,publish-subscribe,Redis,servicestack,Publish Subscribe,作为后续工作,我想了解如何改进手动调用服务。这比我想要的要长,但我觉得背景信息是必要的 执行发布/订阅(广播)时,不使用消息传递API中的正常序列和流,而是在接收到发布/订阅消息时使用IRedisClient、IRedisSubscription获得回调: _subscription.OnMessage = (channel, msg) => { onMessageReceived(ParseJsonMsgToPoco(msg)); }; 然后,操作onMessageReceiv

作为后续工作,我想了解如何改进手动调用服务。这比我想要的要长,但我觉得背景信息是必要的

执行发布/订阅(广播)时,不使用消息传递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));
}
这是可行的,我得到了我的请求和所有这些,但是,我希望它被简化为另一个流,消息传递API中的流,这意味着,请求会进入
服务
类实现,所有正常的样板文件和依赖项注入都会像使用消息传递API一样发生

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

private void Instance_OnMyEvent(object sender, RequestEventArgs e)
{
    using (var myRequestService = HostContext.ResolveService<MyRequestService>(new BasicRequest()))
    {
        myRequestService.Any(e.Request);
    }
}
我看到的效果是,我在
container.addScope
中注册的注入依赖项没有作用域,但看起来是静态的。我之所以看到这一点,是因为我在注入的类中有一个Guid,在这种情况下,Guid总是相同的,而每个请求的Guid应该不同

container.AddScoped<IRedisCache, RedisCache>();
container.addScope();
OnBeforeExecute(在服务的子代中)类似于:

public override void onbeforecute(对象requestDto)
{
base.onbeforecute(requestDto);
IRedisCache缓存=TryResolve();
缓存?.SetGuid(Guid.NewGuid());
}
因此,IRedisCache Guid每次都应该不同,但事实并非如此。但是,当我使用消息传递API“从头到尾”时,这一切都很好。似乎如果我在AppHostBase子代中调用TryResolve,AddScope将被忽略,一个实例被放置在容器中,然后再也不会被删除

管道的哪些部分丢失了

未执行以下操作:

myRequestService.Any(e.Request);
物理上只调用
MyRequestService
类的
Any
C#方法,它不(也不能)做任何其他事情

在服务请求期间调用其他服务的推荐方法是使用

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

HostContext.AppHost.RpcGateway.ExecuteAsync()
对于在服务请求之外执行内部/受信任服务,您可以使用ServiceStack MQ,它应用消息请求/响应筛选器、服务操作筛选器和事件

我已向container.addScope注册


不要使用,如果依赖项是线程安全的,则使用Singleton,否则将它们注册为瞬态。如果您需要通过每个请求存储,请在
IRequest.Items中传递它们

谢谢您的回答,我会看看是否可以在您的指导下解决这个问题。我还意识到
Any
方法不会做任何事情,但我认为
HostContext.ResolveService
可能会起到一些神奇的作用。“不要在HTTP请求之外使用请求范围的依赖项”。在我的例子中,依赖项在AppHostBase子代中注册,并由服务使用(使用消息传递API)。因此,据我所知,我不能真正选择单例,因为有时请求通过消息传递API传入,有时通过发布/订阅传入,如上所述。因此,它是在考虑消息传递API的情况下构建和完成的,我希望将sub/pub方法简化为现有的正确实现。在任何情况下,我将使用您的提示,看看它是如何工作的。谢谢。@Ted所有
ResolveService
做的就是从IOC解析一个新的服务实例,并注入IRequest上下文。您只能在AppHost或ConfigureServices()启动类中注册启动时的依赖项,但如果需要在HTTP请求之外执行服务,则不应使用请求范围的依赖项。好的,在正常的消息传递API中,每个请求需要一个实例,因为我们有“跟踪器”(跟踪请求过程中发生的事情),这需要为每个请求创建,因此,AddScope似乎是一种自然的方法。但正如您所解释的,如果您独家使用消息传递API,这是可行的,但如果我们不在请求范围内(它不是一个普通的HTTP API,它是通过/通过Redis的).Transient似乎是错误的,它会在每次访问接口属性时创建新实例?我认为这意味着失去“状态”。嗯。后续操作:使用
HostContext.AppHost.ExecuteMessage(theMessage);
在这种情况下对我非常有效;即“钩住”它进入请求管道并使所有DI按预期工作。即使在AppHostBase子代中,在管道的方法中执行时,我也从
TryResolve
获得正确的实例,就像在
OnAfterExecute
中一样,这对我来说已经足够了!
myRequestService.Any(e.Request);
HostContext.AppHost.RpcGateway.ExecuteAsync()