gpt4 book ai didi

c# - Rebus:为每条消息添加用户上下文的建议

转载 作者:行者123 更新时间:2023-11-30 17:48:47 25 4
gpt4 key购买 nike

首先让我们将'UserContext' 定义为在用户的正确上下文中执行接收消息所需的一些属性,因此它不仅仅是一个string。 .在我的例子中,这还包括有关用户正在使用哪个应用程序“实例”的数据。

在我看来,有两个主要选项可为消息提供“UserContext”:

  1. 作为标题
  2. 作为消息的基类

当使用Header时,我需要提供自己的序列化,当使用基类时,Rebus会为我解决序列化。

所以我通过一个小示例程序使用了一个基类:

public class UserContext
{
public string Name { get; set; }

public int UserId { get; set; }

public Guid AppId { get; set; }
}

public class UserContextMessageBase
{
public UserContext UserContext { get; set; }
}

public class SimpleMessage : UserContextMessageBase
{
public string Data { get; set; }
}


internal class Program
{
private static void Main(string[] args)
{
using (var adapter = new BuiltinContainerAdapter())
using (var timer = new Timer())
{
//adapter.Register(typeof(UserContextHandler));
adapter.Register(typeof(SimpleMessageHandler));

var bus = Configure.With(adapter)
.Transport(t => t.UseMsmqAndGetInputQueueNameFromAppConfig())
.MessageOwnership(d => d.FromRebusConfigurationSection())

//.SpecifyOrderOfHandlers(o => o.First<UserContextHandler>())

.CreateBus()
.Start();

timer.Elapsed += delegate
{
bus.Send(new Messages.SimpleMessage { Data = Guid.NewGuid().ToString() });
};
timer.Interval = 10000;
timer.Start();

Console.WriteLine("Press enter to quit");
Console.ReadLine();
}
}
}

internal class UserContextHandler : IHandleMessages<UserContextMessageBase>
{
protected UserContext _context;

public void Handle(UserContextMessageBase message)
{
var old = Console.ForegroundColor;
if (_context != null)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Context is already populated");
}

Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine("Processing UserContextMessageBase");
// create the correct Context to process the message
_context = message.UserContext;
Console.ForegroundColor = old;
}
}

internal class SimpleMessageHandler : **UserContextHandler**, IHandleMessages<SimpleMessage>
{
public void Handle(SimpleMessage message)
{
// allow to use the _context to process this message
Console.WriteLine("Received SimpleMessage {0}", message.Data);
}
}

但是当我运行程序时,我看到 SimpleMessage被处理两次。这是'by design吗? ' 或者可能是一个错误?

另一方面,我可以取消注释 UserContextHandler 的注册,并且继承SimpleMessageHandler来自 UserContextHandler ,但我将不得不填充 UserContext进入MessageContext ,并从 SimpleMessageHandler 中使用它.

最佳答案

在我看来,这两种方法都是有效的 - 就我个人而言,我倾向于使用 header ,因为它们噪音较小,并且因为这确实是它们的目的:)但是,正如你正确指出的那样,这需要您以某种方式负责将用户上下文“序列化”为一个或多个 header ,并在收到每条消息后再次反序列化。

虽然在 MessageSentMessageContextEstablished 事件中分别用于发送和接收,但 header 方法可以非常优雅地完成,远离消息处理程序,然后可以在消息上下文中提供用户上下文。

使用消息基类的另一种方法也绝对有效,我可以看到您对传入消息的查找将为每次查找获得一个新的处理程序实例这一事实感到震惊 - 因此,管道将包含两个处理程序实例,然后消息将“尽可能多地”分派(dispatch)(即,每个兼容类型/父类(super class)型一次)到每个处理程序实例,从而有效地处理消息两次。

在你的情况下,我建议你按照你在最后暗示的那样去做:使 UserContextHandler 成为一个单独的处理程序,你确保它在管道中排在第一位,从而允许它隐藏用户MessageContext.GetCurrent().Items 中的上下文,供所有后续处理程序提取。

不过,我很想做一个例子,展示一种方法来做你需要的,但是通过使用标题(可能只是一个 ; 的形式 - 分隔的键列表 -值对,或类似的东西),但恐怕我不能保证在接下来的几天内会提供这样的示例。

让我知道它是否适合你:)

更新:我在 Rebus 的示例存储库中添加了一个示例,它演示了如何获取环境用户上下文并在消息 header 中传递,包括一些关于配置和 DI 的技巧- 它叫做 UserContextHeaders - 检查一下:)

关于c# - Rebus:为每条消息添加用户上下文的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22477098/

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