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

Protobuf-net v3注册DateTimeOffset Surrogate仍报无序列化器错误

问题原因

你碰到的System.InvalidOperationException: No serializer defined for type: System.DateTimeOffset报错,核心原因是Protobuf-net v3的元数据预缓存机制和代理注册时机不匹配,你的Surrogate类写法本身没有逻辑错误。

  • Protobuf-net v3默认会在首次识别到带[ProtoContract]标记的类型时,一次性完成该类型所有序列化成员的元数据构建、全局缓存,构建完成后不会动态响应后续的Surrogate注册更新。你当前把Surrogate注册逻辑放在接口请求方法GetData()内部执行,大概率TestClass、Response<T>这些业务类型的序列化元数据,在你执行注册代码之前就已经被框架初始化完成,后续的注册操作完全不会生效。
  • 补充说明:Protobuf-net v3已经原生支持DateTimeOffset类型的序列化/反序列化,如果你不需要兼容v2版本生成的、采用Ticks+OffsetMinutes存储格式的老数据,完全不需要自定义Surrogate,直接使用该类型即可。
修复方案

按照以下步骤调整即可解决问题:

  1. 调整Surrogate注册时机:把代理注册逻辑移动到应用启动的最早期阶段,绝对不能放在业务请求方法内临时注册。如果是ASP.NET Core项目,就放到Program.cs的服务注册最开头;如果是控制台项目,就放到Main方法第一行执行。
    正确的注册代码如下:
    // 应用启动阶段、任何序列化操作执行前运行
    RuntimeTypeModel.Default.Add(typeof(DateTimeOffset), false)
        .SetSurrogate(typeof(DateTimeOffsetSurrogate));
    
  2. 强制刷新元数据缓存:注册完成后添加如下代码,清空之前可能预生成的旧元数据,强制框架下次执行序列化操作时重新构建完整元数据:
    RuntimeTypeModel.Default.CompileInPlace();
    
  3. 修正代码笔误:你贴出的TestClass定义漏了class关键字,会导致编译错误,需要修正:
    [ProtoContract]
    public class TestClass // 补充缺失的class关键字
    {
        [ProtoMember(1)]
        public DateTimeOffset Time { get; set; }
    }
    
注意事项

如果你在项目中使用了独立的Protobuf格式化组件(比如AspNetCore的Protobuf输出格式化器),这类组件通常会在服务注册阶段就扫描所有[ProtoContract]类型预构建序列化器,你必须在格式化器注册代码之前完成Surrogate配置,否则注册操作依然会失效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 11:00:59