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

C#中如何对静态类JsonSerializer进行依赖注入?

对System.Text.Json进行依赖注入的最佳实践

你的思路方向是对的,但现有方案存在几个明显问题:

  • settings用object类型缺乏类型安全,调用时必须强制转换,容易引发运行时错误
  • 接口方法设计不够灵活,没有利用泛型避免装箱操作
  • 没有通过DI管理序列化配置,每次调用都传参数冗余繁琐

下面是更合理的实现方案,兼顾类型安全、可扩展性和DI友好性:

1. 定义类型安全的序列化接口

把参数换成具体的JsonSerializerOptions,同时提供泛型重载优化性能:

public interface ISerializer
{
    // 泛型序列化,避免装箱,支持自定义选项
    string Serialize<T>(T value, JsonSerializerOptions? options = null);
    
    // 对象序列化,兼容非泛型场景
    string Serialize(object value, JsonSerializerOptions? options = null);
    
    // 泛型反序列化,支持自定义选项
    T? Deserialize<T>(string json, JsonSerializerOptions? options = null);
}

2. 实现System.Text.Json适配类

通过构造函数注入默认序列化选项,让DI统一管理配置:

public class SystemTextJsonSerializer : ISerializer
{
    private readonly JsonSerializerOptions _defaultOptions;

    public SystemTextJsonSerializer(JsonSerializerOptions defaultOptions)
    {
        _defaultOptions = defaultOptions ?? throw new ArgumentNullException(nameof(defaultOptions));
    }

    public string Serialize<T>(T value, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Serialize(value, options ?? _defaultOptions);
    }

    public string Serialize(object value, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Serialize(value, options ?? _defaultOptions);
    }

    public T? Deserialize<T>(string json, JsonSerializerOptions? options = null)
    {
        return JsonSerializer.Deserialize<T>(json, options ?? _defaultOptions);
    }
}

3. 注册依赖注入

在项目的DI容器中注册默认配置和序列化器(以.NET 6+为例):

// 注册全局默认的JsonSerializerOptions,按需配置规则
builder.Services.AddSingleton<JsonSerializerOptions>(new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    WriteIndented = false,
    IgnoreNullValues = true
    // 其他自定义配置...
});

// 注册序列化器实现
builder.Services.AddSingleton<ISerializer, SystemTextJsonSerializer>();

4. 业务代码中使用

直接通过构造函数注入ISerializer即可,既可以用默认配置,也能临时传自定义选项:

public class MessageSender
{
    private readonly ISerializer _serializer;

    public MessageSender(ISerializer serializer)
    {
        _serializer = serializer;
    }

    public void SendMessage(Message message)
    {
        // 使用全局默认配置序列化
        string json = _serializer.Serialize(message);
        
        // 临时使用自定义选项(比如格式化输出)
        var customOptions = new JsonSerializerOptions { WriteIndented = true };
        string prettyJson = _serializer.Serialize(message, customOptions);
        
        // 后续发送逻辑...
    }
}

5. 切换序列化库(比如Newtonsoft.Json)

只要实现同一个ISerializer接口,就能无缝替换,业务代码无需修改:

public class NewtonsoftJsonSerializer : ISerializer
{
    private readonly JsonSerializerSettings _defaultSettings;

    public NewtonsoftJsonSerializer(JsonSerializerSettings defaultSettings)
    {
        _defaultSettings = defaultSettings ?? throw new ArgumentNullException(nameof(defaultSettings));
    }

    public string Serialize<T>(T value, JsonSerializerOptions? options = null)
    {
        // 可根据需求转换System.Text.Json选项到Newtonsoft配置,或直接用默认
        return JsonConvert.SerializeObject(value, _defaultSettings);
    }

    public string Serialize(object value, JsonSerializerOptions? options = null)
    {
        return JsonConvert.SerializeObject(value, _defaultSettings);
    }

    public T? Deserialize<T>(string json, JsonSerializerOptions? options = null)
    {
        return JsonConvert.DeserializeObject<T>(json, _defaultSettings);
    }
}

注册时替换实现即可:

builder.Services.AddSingleton<JsonSerializerSettings>(new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver(),
    Formatting = Formatting.None,
    NullValueHandling = NullValueHandling.Ignore
});

builder.Services.AddSingleton<ISerializer, NewtonsoftJsonSerializer>();

6. 测试场景使用

可以用Mock工具(比如Moq)模拟ISerializer,或者用自定义选项验证序列化逻辑:

[Test]
public void SendMessage_ShouldCallSerialization()
{
    // Mock序列化器
    var mockSerializer = new Mock<ISerializer>();
    var testMessage = new Message { Id = 1, Content = "Test Content" };
    
    mockSerializer.Setup(s => s.Serialize(testMessage)).Returns("{\"id\":1,\"content\":\"Test Content\"}");
    
    var sender = new MessageSender(mockSerializer.Object);
    sender.SendMessage(testMessage);
    
    // 验证序列化方法被正确调用
    mockSerializer.Verify(s => s.Serialize(testMessage), Times.Once);
}

方案优势

  • 类型安全:避免了object类型的强制转换,减少运行时异常
  • 配置集中:全局序列化规则由DI统一管理,无需重复配置
  • 高度可扩展:切换序列化库只需替换实现类,业务逻辑无侵入
  • 测试友好:轻松Mock或自定义配置,验证不同场景下的序列化行为

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 06:37:08