You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不同程序集间用Rebus发布订阅相同DTO?

解决Rebus跨程序集同名类型的发布订阅问题

你的问题核心是Rebus默认使用类型全名, 程序集名称作为消息的唯一标识,导致订阅端试图加载发布端程序集A中的TYPEA,从而抛出格式异常。通过自定义IMessageTypeNameConvention,可以实现仅用命名空间+类型名作为消息标识,无需共享程序集。

自定义消息类型命名约定

实现IMessageTypeNameConvention接口,剥离程序集信息,仅保留命名空间和类型名:

public class NamespaceOnlyTypeNameConvention : IMessageTypeNameConvention
{
    public string GetMessageTypeName(Type type)
    {
        // 返回命名空间+类型名,不包含程序集信息
        return $"{type.Namespace}.{type.Name}";
    }

    public Type GetTypeFromMessageTypeName(string messageTypeName)
    {
        // 在当前程序集中查找匹配的类型
        return Type.GetType(messageTypeName, throwOnError: true);
    }
}

在两端配置Rebus

发布端和订阅端都需要替换默认的消息命名约定,确保两端使用相同的规则解析消息类型:

发布端配置示例

// 示例使用内置激活器和RabbitMQ传输,可根据实际情况替换
var publisherActivator = new BuiltinHandlerActivator();

Configure.With(publisherActivator)
    .Transport(t => t.UseRabbitMq("amqp://localhost", "publisher-queue"))
    .MessageNaming(m => m.UseCustomMessageTypeNameConvention(new NamespaceOnlyTypeNameConvention()))
    .Start();

订阅端配置示例

var subscriberActivator = new BuiltinHandlerActivator();
// 注册TYPEA的消息处理程序
subscriberActivator.Register(() => new TypeAHandler());

Configure.With(subscriberActivator)
    .Transport(t => t.UseRabbitMq("amqp://localhost", "subscriber-queue"))
    .Subscriptions(s => s.UseJsonFile(@"subscriptions.json"))
    .MessageNaming(m => m.UseCustomMessageTypeNameConvention(new NamespaceOnlyTypeNameConvention()))
    .Start();

// 订阅TYPEA消息
await subscriberActivator.Bus.Subscribe<TypeA>();

关键注意事项

  • 两端的TYPEA类型必须结构完全一致:字段/属性的名称、类型、可访问性都要匹配,否则序列化/反序列化会失败。
  • 确保两端使用的序列化器配置相同(比如用Newtonsoft.Json时,统一日期格式、空值处理等规则)。
  • 避免不同业务逻辑的类型使用完全相同的命名空间+类型名,防止消息路由混乱。

内容的提问来源于stack exchange,提问作者Massimo Lavermicocca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:58:14