MassTransit Job Consumer含List<T>成员消息反序列化失败
MassTransit v8.0.3 JobConsumer 反序列化异常修复
异常核心原因
异常触发链路:
- 提交作业时使用匿名对象构造
ProcessFoos接口类型消息,Newtonsoft序列化器初始序列化时未携带集合元素Foo的具体类型元数据 - JobService 持久化作业消息后,在FinalizeJobConsumer环节二次反序列化消息时,
InterfaceProxyConverter默认将接口消息的所有引用类型属性识别为需要生成动态代理的接口类型,尝试将foos[0]位置的JSON内容按接口代理规则解析 - 实际该位置存储的是无类型元数据的JSON结构,序列化器误判为数组结构,最终抛出数组无法转
Foo对象的异常
修复步骤
按以下顺序调整即可解决问题:
- 替换匿名对象消息构造逻辑,显式定义消息契约的实现类型,保证类型信息在发送链路完整传递
// 定义消息实现类 public record ProcessFoosCommand : ProcessFoos { public List<Foo> Foos { get; init; } } // 调整作业提交代码 var foos = new List<Foo> { new Foo { FooID = "foo" } }; Response<JobSubmissionAccepted> response = await _processFoosClient.GetResponse<JobSubmissionAccepted>(new ProcessFoosCommand { Foos = foos }); - 补充Newtonsoft序列化配置,开启自动类型元数据写入,保证二次反序列化时类型识别正确
x.UsingRabbitMq((context, cfg) => { cfg.UseNewtonsoftJsonSerializer(); cfg.UseNewtonsoftJsonDeserializer(); // 补充序列化/反序列化配置 cfg.ConfigureNewtonsoftJsonSerializer(settings => { // 自动为非基础类型写入类型元数据 settings.TypeNameHandling = TypeNameHandling.Auto; return settings; }); cfg.ConfigureNewtonsoftJsonDeserializer(settings => { settings.TypeNameHandling = TypeNameHandling.Auto; return settings; }); // 原有其他配置... });
验证标准
调整后作业持久化存储的消息体中,foos数组下的每个元素会携带对应类型元数据,格式为:
{ "foos": [ { "$type": "MyNamespace.Foo, 你的程序集名称", "FooID": "foo" } ] }
此时反序列化逻辑可正确识别Foo为具体类,不会触发接口代理转换逻辑,IJobConsumer<ProcessFoos>.Run方法可正常进入执行。
内容的提问来源于stack exchange,提问作者nhdev
相关产品推荐
相关产品推荐

