首页
/ MessagePack-CSharp 中处理字符串反序列化的 FormatterNotRegisteredException 问题

MessagePack-CSharp 中处理字符串反序列化的 FormatterNotRegisteredException 问题

2025-06-04 14:13:32作者:贡沫苏Truman

在使用 MessagePack-CSharp 进行数据序列化和反序列化时,开发者可能会遇到一个常见问题:当尝试反序列化包含字符串类型的数据时,系统抛出 FormatterNotRegisteredException 异常,提示字符串类型未在解析器中注册。本文将深入分析这个问题产生的原因,并提供完整的解决方案。

问题现象

当开发者使用 MessagePack-CSharp 的源码生成功能时,可能会遇到如下错误:

FormatterNotRegisteredException: 'System.String is not registered in resolver

这个错误通常发生在以下场景:

  1. 使用了 [GeneratedMessagePackResolver] 特性生成自定义解析器
  2. 尝试反序列化包含字符串类型的对象
  3. 仅使用了生成的解析器实例作为反序列化选项

问题根源

MessagePack-CSharp 的源码生成器只会为标记了 [MessagePackObject] 的自定义类型生成解析器。对于 .NET 内置的基本类型(如 System.String),它们属于 MessagePack 的"内置类型",默认情况下不会包含在生成的解析器中。

这些内置类型的解析器实际上存在于 BuiltinResolver 中。当开发者仅使用生成的解析器而忽略了内置解析器时,系统就无法找到字符串类型的格式化器,从而导致上述异常。

解决方案

正确的做法是创建一个复合解析器(CompositeResolver),将生成的解析器与内置解析器组合使用。以下是完整的解决方案:

  1. 首先确保你的自定义类型已正确标记 [MessagePackObject] 特性
  2. 使用 GeneratedMessagePackResolver 生成解析器
  3. 创建复合解析器,将生成的解析器与内置解析器组合
[GeneratedMessagePackResolver]
internal partial class MessagepackBouncyHsmResolver
{
    // 可以添加静态属性方便访问
    public static IFormatterResolver Instance => MessagepackBouncyHsmResolver.Instance;
}

// 使用时创建复合解析器
var resolver = CompositeResolver.Create(
    BuiltinResolver.Instance,
    MessagepackBouncyHsmResolver.Instance
);

var options = MessagePackSerializerOptions.Standard.WithResolver(resolver);

最佳实践

  1. 对于简单项目:可以直接使用 MessagePackSerializerOptions.Standard,它已经包含了所有必要的解析器。

  2. 对于使用源码生成的项目

    • 总是创建复合解析器
    • 考虑将解析器配置封装为静态属性方便复用
    • 对于性能敏感场景,可以缓存解析器实例
  3. 扩展性考虑:如果需要支持更多内置类型或第三方类型,可以在复合解析器中添加相应的解析器实例。

总结

MessagePack-CSharp 通过分离内置类型和自定义类型的解析器实现了更好的模块化设计。理解这种设计模式后,开发者就能正确处理类型解析的问题。记住,当使用源码生成功能时,总是要考虑将生成的解析器与内置解析器组合使用,这样才能确保所有类型都能被正确序列化和反序列化。

通过本文的解决方案,开发者可以避免 FormatterNotRegisteredException 异常,确保字符串等内置类型能够与自定义类型一起正常工作。

登录后查看全文
热门项目推荐
相关项目推荐