gpt4 book ai didi

c# - ServiceStack.Redis : Configure so that the request and response class/dto is the same class?

转载 作者:行者123 更新时间:2023-12-03 06:44:55 24 4
gpt4 key购买 nike

一段时间以来,我一直在使用 ServiceStack,我很清楚基于消息的 API 设计是首选,这是我在一些基于 REST 的 API 中使用的东西。

我现在正在研究 Redis/MQ 库,并且一如既往地享受 ServiceStack 的结构和功能。但是,我正在考虑用 MQ 服务器替换一些旧的通信代码,并且有 tested out some SS examples ,而且效果很好。

但是,我正在使用的一些遗留代码对传出请求和响应使用相同的类,例如 GetSomething发送,回复是同一个类的实例GetSomething ,但具有类似 GetSomething.Result 的属性包含回复/结果。

由于我想直接替换当前的通信模型,因此我想看看是否可以“开箱即用”支持这种情况,但我没有真正找到解决此问题的方法。当我在具有处理程序的消费者中出现这样的事情时:

mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);

以及想要回复的发布者:
mqServer.RegisterHandler<GetSomething>(m => {...});

发生的事情是发布者立即接收请求,并且它永远不会到达消费者。如果我删除发布者中回复的监听器,它会到达消费者,但是当消费者使用相同的 DTO 进行回复时, GetSomething ,它陷入了一个永恒的循环,因为我认为回复被放置在同一个 MQ 队列中。

是否有使用 ServiceStack 解决此问题的聪明方法?

我有一些可能的解决方法的想法,但我想知道这是否可以以更好、更聪明的方式解决。

最佳答案

我只是想分享一种解决方法,它可能不是最漂亮的,但似乎有效。如果有更好的方法来做到这一点,我仍然很感兴趣。

发布者:

发布者为 RedisMqServer 分配一个 RequestFilter,并在该方法中修改 .Body ,用实际请求替换包装器。

然后发布者调用 .RegisterHandler一次用于响应包装器类,然后按预期用于每个实际/真实的处理程序。这将导致调用正确的服务处理程序:

    public RedisClient(string name)
{
Name = name;
redisFactory = new PooledRedisClientManager("localhost:6379");
mqServer = new RedisMqServer(redisFactory, retryCount: 2);

mqServer.RequestFilter = RequestFilter;

// Response wrapper, ContainerResponse implements IProtocolContainer
mqServer.RegisterHandler<ContainerResponse>(m =>
{
return m;
});

mqServer.RegisterHandler<GetSomething>(m =>
{
// m.Body is here an GetSomething
return null;
});
mqServer.Start();
}

private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
{
if (message.Body is IProtocolContainer protocolContainer)
{
message.Body = protocolContainer.TheRequest;
}
return message;
}

public void AddMessage<T>(T theRequest) where T : CoreRequest
{
using (var mqClient = mqServer.CreateMessageQueueClient())
{
mqClient.Publish(new ContainerRequest(theRequest));
}
}
}

消费者:

同样的原则也适用于消费者:
    public override void Configure(Container container)
{
container.Register(new ConsumerInfo() { Name = ServiceName });

var redisFactory = new PooledRedisClientManager("localhost:6379");
container.Register<IRedisClientsManager>(redisFactory);
var mqHost = new RedisMqServer(redisFactory, retryCount: 2);

mqHost.RequestFilter = RequestFilter;
mqHost.ResponseFilter = ResponseFilter;

mqHost.RegisterHandler<ContainerRequest>(base.ExecuteMessage);
mqHost.RegisterHandler<GetSomething>(base.ExecuteMessage);
mqHost.Start();
}

private object ResponseFilter(object arg)
{
return new ContainerResponse(arg as CoreRequest);
}

private ServiceStack.Messaging.IMessage RequestFilter(ServiceStack.Messaging.IMessage message)
{
if (message.Body is IProtocolContainer protocolContainer)
{
System.Diagnostics.Debug.WriteLine($"\tReplaced Body with {protocolContainer.TheRequest.GetType().Name}");
message.Body = protocolContainer.TheRequest;
}
return message;
}
}

关于c# - ServiceStack.Redis : Configure so that the request and response class/dto is the same class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61621838/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com