修改现有消息类让.net core项目支持Protobuf - 【无需使用 [ProtoBuf.ProtoContract] 的方法】
2021-04-25 23:27
标签:als 初始 出错 复杂 protoc 注意事项 param model 关系 第二次发博客,希望大家多多鼓励!!! 又接无上老板的一个需求,需要让.net core消息发送端跟消息接收端通信的消息是protobuf格式的(基于protobuf比json小一倍数据量,独特的编码、没有fieldname等),但现有项目的消息类数量巨多,按照网上的方案是安装protobuf.net 这个nuget包,然后需要给消息类一个一个添加[ProtoBuf.ProtoContract]、[ProtoBuf.ProtoMember(index)]等Attributes,更可悲的是,还得处理继承的问题,也就是要有类似如下这种代码: 关于为什么要设置上面这些attributes,跟protobuf的原理息息相关,有兴趣的朋友可以看看这篇文章,而关于protobuf.net的基本用法,可以参考这里 对于项目存在巨多消息类,显然这么一个一个的加attributes既费时又容易出错。我拿着这个需求,怀着忐忑的心,一通操作,终于找到了想要的方案,也就是找到了without attributes的方法,顺便悄悄的告诉您,貌似国内还没谁发现这个方法 : 使用RuntimeTypeModel.Default进行类型及其Properties的配置 动动脑筋,上面的代码,如果不用attributes而是用RuntimeTypeModel.Default进行类型及其Properties的配置的话,代码就是的: 但是仔细想想其实原理跟添加attributes是一个道理, 有了上面这个方法,我们就会自然而然想到对所有消息类使用RuntimeTypeModel.Default进行类型及其Properties的配置,但我们又不可能费时费力的给项目的每个消息实体类添加这些代码,那么这里就想到了使用反射找出项目中所有消息实体类,然后一个一个的操作 先看看我们的消息基类: 很简单吧,然后看看我们给类动态添加“[ProtoBuf.*]”这些attributes的核心代码: 其实上面就是所有代码了,使用的话,就是在消息发送跟消息接收程序启动后,就调用上面的Init方法,仅需要调用一次额。当然聪明的你,肯定已经想到将它封装成一个工具类了,哈哈。 细心的朋友可以注意到,我并没有调用AddSubType(其实我消息类的某些property确实是复杂类型且有父子关系的)以及可能你也发现了在上面的“想办法解决,咱们不干体力活”章节中父子类型注册到RuntimeTypeModel中有一个先后顺序,但上面的代码在实际使用过程中也就是消息接收端反序列化protobuf消息时并没出现问题。如果你的项目使用了上面的代码,结果发现反序列化不了,特别是抛了不能识别类型的错误,那么很可能就是我所说的两点要处理下。 希望大家多多评论,2020年身体健康,过得顺心!!! 修改现有消息类让.net core项目支持Protobuf - 【无需使用 [ProtoBuf.ProtoContract] 的方法】 标签:als 初始 出错 复杂 protoc 注意事项 param model 关系 原文地址:https://www.cnblogs.com/sutong/p/12222646.html前言
[ProtoContract]
[ProtoInclude(10, typeof(Male))]
public class Person
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
[ProtoMember(3)]
public Address Address { get; set;}
}
[ProtoContract]
public class Male : Person
{
}
[ProtoContract]
public class Address
{
[ProtoMember(1)]
public string Line1 {get;set;}
[ProtoMember(2)]
public string Line2 {get;set;}
}
找解决方案,咱们不干体力活
var personMetaType = RuntimeTypeModel.Default.Add(typeof (Person), false);
personMetaType.Add(1, "Id");
personMetaType.Add(2, "Name");
personMetaType.Add(3, "Address");
var addressMetaType = RuntimeTypeModel.Default.Add(typeof(Address), false);
addressMetaType.Add(1, "Line1");
addressMetaType.Add(2, "Line2");
// 给父类metaType添加子类型
personMetaType.AddSubType(10, typeof (Male));
// 然后添加子类型
RuntimeTypeModel.Default.Add(typeof(Male), false);
RuntimeTypeModel.Default.Add(typeof(Female), false);
具体实现
///
static bool isInit = false; // 避免重复初始化
///
注意事项
文章标题:修改现有消息类让.net core项目支持Protobuf - 【无需使用 [ProtoBuf.ProtoContract] 的方法】
文章链接:http://soscw.com/index.php/essay/79562.html