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

EasynetQ bus.Subscribe无响应,抛出'messageType must not be null'异常求助

解决EasyNetQ "messageType must not be null" 错误问题

从你的错误日志和代码来看,核心问题是EasyNetQ在反序列化消息时,无法根据消息属性里的Type值匹配到对应的CLR类型,导致抛出ArgumentNullException。下面是具体的排查和解决步骤:

1. 确认发布/订阅端的消息类型完全一致

你的消息Type属性显示为Milkshop.Common.MilkOrderRequest:Milkshop.Common,这说明发布端的MilkOrderRequest类型属于Milkshop.Common程序集。请务必确保:

  • 订阅端引用的是同一个类库中的MilkOrderRequest,而非复制代码重新定义的类型
  • 两端的程序集名称、版本、强签名状态完全一致(如果启用了强签名)

如果是跨服务场景,建议把消息类型封装在独立的类库NuGet包中,让发布和订阅端统一引用,从根源避免类型不匹配问题。

2. 显式配置消息类型映射

如果两端的类型全名存在差异(比如程序集版本不同),可以自定义类型名称序列化规则,让EasyNetQ能正确映射类型:

自定义TypeNameSerializer

在发布和订阅端都配置这个自定义序列化器:

// 创建Bus时注册自定义类型序列化器
var bus = RabbitHutch.CreateBus("host=192.168.153.128:5672;username=user;password=pass", x =>
{
    x.Register<ITypeNameSerializer, FixedTypeNameSerializer>();
});

// 自定义实现
public class FixedTypeNameSerializer : ITypeNameSerializer
{
    public string Serialize(Type type)
    {
        // 给MilkOrderRequest指定一个固定的短名称
        if (type == typeof(MilkOrderRequest))
            return "MilkOrderRequest";
        // 其他类型保留默认规则
        return type.AssemblyQualifiedName;
    }

    public Type Deserialize(string typeName)
    {
        // 把短名称映射回实际CLR类型
        if (typeName == "MilkOrderRequest")
            return typeof(MilkOrderRequest);
        return Type.GetType(typeName);
    }
}

3. 修复发布端的消息属性配置

你的发布代码未设置ContentType,EasyNetQ默认使用JSON序列化,建议显式配置,同时确保Type属性和订阅端规则一致:

using (IAdvancedBus bus = RabbitHutch.CreateBus("host=192.168.153.128:5672;username=user;password=pass").Advanced) 
{ 
    IExchange exchange = bus.ExchangeDeclare("milk.api", ExchangeType.Topic); 
    IQueue queue = bus.QueueDeclare("milkorderqueue"); 
    IBinding binding = bus.Bind(exchange, queue, "#"); 

    var message = new Message<MilkOrderRequest>(milkOrder);
    // 显式指定JSON内容类型
    message.Properties.ContentType = "application/json";
    // 使用自定义的统一类型名称
    message.Properties.Type = "MilkOrderRequest";

    bus.Publish<MilkOrderRequest>(exchange, "#", true, message); 
} 
return new HttpResponseMessage(System.Net.HttpStatusCode.OK);

4. 简化订阅端代码(使用IBus而非AdvancedBus)

如果不需要AdvancedBus的高级功能,用普通的IBus.Subscribe更简洁,同时确保配置和发布端一致:

IBus bus = RabbitHutch.CreateBus(@"host=192.168.153.128:5672;username=user;password=pass", x =>
{
    x.Register<ITypeNameSerializer, FixedTypeNameSerializer>();
});

bus.Subscribe<MilkOrderRequest>("my_subscription_id", message => 
{ 
    Console.WriteLine($"Order recieved: {message.Milk}."); 
}, config => 
{ 
    config.WithQueueName("milkorderqueue"); 
});

错误根源总结

EasyNetQ依赖消息的Type属性定位反序列化所需的CLR类型,以下情况都会触发这个异常:

  • 订阅端未引用包含目标类型的程序集
  • 消息Type属性的值与订阅端的类型全名不匹配
  • 程序集加载异常(比如版本冲突导致无法加载类型)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 09:08:53