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

通过反射获取类型反序列化Service Bus JSON消息遇空值求助

解决Service Bus消息反序列化中Type.GetType返回null的问题

问题描述

从Service Bus接收JSON格式消息,消息结构包含JobType、JobArgsType和JobArgs字段。最初尝试通过反射获取JobArgsType指定的类型(如DispatcherWeb.Infrastructure.BackgroundJobs.ImportJobArgs)反序列化JobArgs时,出现Cannot resolve symbol 'className'错误;改用非泛型的JsonSerializer.Deserialize方法后,Type.GetType(messageObject.JobArgsType)返回null,无法获取目标类型。

初始代码

private static async Task ReceiveMessage(string serviceBusQueueName, ServiceBusClient client)
{
    var processor = client.CreateProcessor(serviceBusQueueName, new ServiceBusProcessorOptions());
    processor.ProcessMessageAsync += async (messageArgs) =>
    {
        var messageObject = JsonSerializer.Deserialize<MessageObject>(messageArgs.Message?.Body.ToString());
        var className = Type.GetType(messageObject.JobArgsType);
        var data = JsonSerializer.Deserialize<className>(messageObject.JobArgs.ToString());
        await messageArgs.CompleteMessageAsync(messageArgs.Message);
    };

    processor.ProcessErrorAsync += async (messageArgs) =>
    {
        Console.WriteLine(messageArgs.Exception.Message);
    };

    await processor.StartProcessingAsync();
}

internal class MessageObject
{
    public string JobType { get; set; }
    public string JobArgsType { get; set; }
    public object JobArgs { get; set; }
}

修改后代码

processor.ProcessMessageAsync += async (messageArgs) =>
{
    var messageObject = JsonSerializer.Deserialize<MessageObject>(messageArgs.Message?.Body.ToString());
    var className = Type.GetType(messageObject.JobArgsType);
    var data = JsonSerializer.Deserialize(messageObject.JobArgs.ToString(), className);
    await messageArgs.CompleteMessageAsync(messageArgs.Message);
};

错误原因

Type.GetType(string)方法仅在传入完全限定类型名(命名空间+类名)+程序集名称时,才能跨程序集正确找到类型。如果仅传入命名空间加类名,只有当目标类型位于当前执行程序集或系统核心程序集(如mscorlib)时才有效。你的ImportJobArgs大概率在其他自定义程序集中,因此只传DispatcherWeb.Infrastructure.BackgroundJobs.ImportJobArgs会导致返回null。

另外,初始代码中的Cannot resolve symbol 'className'错误,是因为泛型方法的类型参数需要编译时常量,不能用变量作为泛型参数,改用非泛型版Deserialize的方向是正确的。

解决方案

1. 补充程序集信息到JobArgsType字段

发送消息时,将类型的完全限定名+程序集名称传入JobArgsType,格式示例:

DispatcherWeb.Infrastructure.BackgroundJobs.ImportJobArgs, DispatcherWeb

(其中DispatcherWeb是目标类型所在的程序集名称)

修改后Type.GetType就能直接正确解析类型。

2. 手动指定程序集查找类型

如果无法修改发送端的JobArgsType内容,可以通过已知类型定位程序集,再从中查找目标类型:

// 方式1:通过同程序集的已知类型获取程序集
var assembly = typeof(SomeTypeInSameAssembly).Assembly; 
// 方式2:直接加载目标程序集(需确保程序集已被加载)
// var assembly = Assembly.Load("DispatcherWeb");

// 从程序集中查找类型
var targetType = assembly.GetType(messageObject.JobArgsType);
if (targetType != null)
{
    var data = JsonSerializer.Deserialize(messageObject.JobArgs.ToString(), targetType);
    // 后续业务处理
}

注:SomeTypeInSameAssembly是与ImportJobArgs位于同一程序集的任意类型。

3. 维护类型映射字典

如果涉及的JobArgs类型数量有限,可提前维护一个类型映射字典,避免反射查找的不确定性:

// 提前初始化类型映射
private static readonly Dictionary<string, Type> _jobArgTypeMap = new Dictionary<string, Type>
{
    { "DispatcherWeb.Infrastructure.BackgroundJobs.ImportJobArgs", typeof(DispatcherWeb.Infrastructure.BackgroundJobs.ImportJobArgs) },
    // 其他需要处理的类型依次添加
};

// 接收消息时使用字典获取类型
processor.ProcessMessageAsync += async (messageArgs) =>
{
    var messageObject = JsonSerializer.Deserialize<MessageObject>(messageArgs.Message?.Body.ToString());
    if (_jobArgTypeMap.TryGetValue(messageObject.JobArgsType, out var targetType))
    {
        var data = JsonSerializer.Deserialize(messageObject.JobArgs.ToString(), targetType);
        // 处理业务逻辑
    }
    await messageArgs.CompleteMessageAsync(messageArgs.Message);
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:03:16