C# protobuf-net泛型继承报PBN0012警告原因及免重写解决方案
警告性质说明
这个PBN0012警告是protobuf-net 3.x及以上版本的预期行为,不属于框架bug。
根本原因在于:你给开放泛型类型BaseState<T>(未填充泛型参数的泛型定义)添加了[ProtoInclude]声明子类,但实际运行时ExampleState继承的是构造后的封闭泛型类型BaseState<ExampleModel>,二者是完全不同的运行时类型,框架校验时无法匹配继承关系,因此触发警告。
低改造成本解决方案
无需重写现有模型结构,可直接选择以下任意一种方案修复:
方案1:启动时批量动态注册继承关系(推荐)
仅需要在应用初始化阶段添加一段反射注册逻辑,完全不需要修改现有模型的特性定义,适配大量现有模型的场景:
// 程序启动时执行一次 var baseOpenType = typeof(BaseState<>); // 扫描所有继承自BaseState<>的子类 var subTypes = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => !t.IsAbstract && t.BaseType != null && t.BaseType.IsGenericType && t.BaseType.GetGenericTypeDefinition() == baseOpenType); foreach (var subType in subTypes) { // 获取子类对应的封闭泛型基类 var constructedBaseType = subType.BaseType; // 注册继承关系,字段编号和你之前[ProtoInclude]填的保持一致即可 RuntimeTypeModel.Default.Add(constructedBaseType, true) .AddSubType(1, subType); }
注册完成后删除原来BaseState<T>上的[ProtoInclude(1, typeof(ExampleState))]特性即可消除警告。
方案2:新增非泛型基类适配
如果不想加运行时代码,也可以新增一层非泛型基类承载继承声明,原有模型逻辑完全不变:
// 新增非泛型基类 [ProtoContract] [ProtoInclude(1, typeof(ExampleState))] public abstract class BaseState { [ProtoMember(3)] public abstract string Id { get; } } // 原有泛型基类调整继承关系 [ProtoContract] public abstract class BaseState<T> : BaseState { [ProtoMember(2)] public T Model { get; set; } public override string Id => this.Model.Id; } // 原有子类完全不需要修改 [ProtoContract] public class ExampleState: BaseState<ExampleModel> { [ProtoMember(1)] public DateTimeOffset LastSeenAt { get; set; } }
内容的提问来源于stack exchange,提问作者FranzHuber23
相关产品推荐
相关产品推荐

