当前位置: 首页 > 编程语言 > C#

具有扩展的协议缓冲区分享

时间:2023-04-11 03:01:00 C#

C#学习教程:带有扩展的协议缓冲区这似乎有点不清楚,所以我会直接跳到问题上。我正在编写一个程序集来支持各种任务,其中一项涉及描述结构化数据。使用ProtocolBuffers的最佳时机。使用ProtocolBuffers的主要类称为StateDefinition。这是我为它准备的.proto文件:packageKannon.State;消息StateDefinition{枚举StateTypes{GRAPHICS=0;音频=1;头脑=2;物理学=3;网络=4;通用=5;}重复StateTypesrequiredStates=1;可选的GraphicsStateDefGraphics=2;可选AudioStateDef音频=3;(etc)}messageGraphicsStateDef{将100扩展到最大值;}messageAudioStateDef{将100扩展到最大值;(等)我的目标是允许稍后使用必填字段扩展那些_StateDef消息。但是,此扩展将独立于我正在编写的库。Kagents.dll->处理StateDefinition解析等。引用Kagents.dll的东西->有一个带有“扩展GraphicsStateDef”的protobuff文件来定义所需的状态。我希望定义“extendGraphicsStateDef”会生成允许我使用属性访问这些字段并避免繁琐的“Extendible.AppendValue()”和GetValue()语法的代码。我设计的一个看起来很老套的解决方案是在引用的DLL中使用如下扩展方法定义一个类:返回Extensible.GetValue(def,Fields.someValue);}publicstaticvoidsomeValue(thisState.graphicsStateDefdef,Int32value){Extensible.AppendValue(def,fields.someValue,value);如果有人能想到更好的方法,我将不胜感激。=)另外,我不确定我对问题的描述是否清楚,所以如果我可以提供任何澄清或更多信息,请告诉我。=)编辑:所以,经过深思熟虑,并意识到我正在处理错误的问题。StateReference应该存储不同游戏状态的列表。同样,它存储一个StateDefinition,它应该描述这个状态所指的状态。目前,我正在尝试将状态缓冲区反序列化为不同的类(GraphicsStateDef),而我确实应该反序列化为状态对象本身。所以我需要重新考虑设计,使StateDefinition成为流的容器,并为“repeatedStateTypesrequiredStates=1”字段提取足够的信息。然后,在引用程序集中,流的其余部分可以反序列化为相应的状态。有没有人对如何处理这个有建议?正在制定一些想法,但没有什么具体的,我喜欢其他人的意见。我是protobuf-net的作者。我没有添加任何内容来解决直接呈现场景(除了可扩展代码),但我愿意接受有关您认为它应该做什么的建议。我还需要检查“protoc”(我在代码生成之前用来解析.proto的.proto编译器)是否允许我区分常规成员和扩展成员。最终答案:好的,所以,我几天前找到了解决方案,我只是更新它以防其他人遇到同样的问题。整个问题源于我没有意识到protobuf-net可以支持byte[]。所以,这是我的解决方案:以上是C#学习教程的全部内容:protocolbufferwithextension。如果对大家有用,需要进一步了解C#学习教程,希望大家多多关注——命名空间观音。State{//////ReferenceDefinition总体上描述了引用的布局。///它告诉它应该有什么状态,并存储流缓冲区以供以后序列化。///[ProtoBuf.ProtoContract]publicclassReferenceDefinition{//////有几种内置状态类型,以及对“通用”状态的基本支持。///publicenumStateType{Graphics=0,Audio,Mind,Physics,Network,Generic}//////表示ReferenceDefinition中应该存在的状态///[ProtoBuf.ProtoMember(1)]Listm_StatesPresent=新列表();//////表示StateDefinitions列表,其中包含每种不同类型状态的缓冲区。///[ProtoBuf.ProtoMember(2)]列表m_StateDefinition=newList();//////将映射到类型的状态添加到此引用定义。//////要添加的状态类型///状态要添加的定义。publicvoidAddState(StateTypetype,StateDefinitiondef){//每种类型只强制执行1个,Generic除外,它可以有任意多个。如果(m_StatesPresent.Contains(type)&&type!=StateType.Generic)返回;m_StatesPresent.Add(类型);m_StateDefinition.Add(def);}}//////表示一些游戏状态的定义,存储要重新映射到状态的原型缓冲数据。///[ProtoBuf.ProtoContract]publicclassStateDefinition{//////状态名称///[ProtoBuf.ProtoMember(1)]stringm_StateName;//////用于存储“数据”以供以后序列化的字节数组。///[ProtoBuf.ProtoMember(2)]byte[]m_Buffer;//////状态定义的构造函数,受保护以强制执行打包和解包功能以确保事物安全。//////状态类型的名称。///用于从受保护的StateDefinition(Stringname,byte[]buff)构建状态的字节缓冲区{m_StateName=name;m_Buffer=浅黄色;}//////将StateDefinition解包到GameState//////要解包到的Gamestate类型。必须定义Protobuf合约。///状态定义解包。///解压后的状态数据。publicstaticTUnpack(StateDefinitiondef)whereT:GameState{//确保我们解包为正确的状态类型。如果(typeof(T).Name==def.m_StateName)返回ProtoBuf.Serializer.Deserialize(newMemoryStream(def.m_Buffer));else//否则,返回Null的等价物。返回默认值(T);}//////将状态类型打包成状态定义//////Gamestate来打包。Upst定义protobuf合约。///状态打包。///从传入状态序列化的状态定义。publicstaticStateDefinitionPack(Tstate)whereT:GameState{//使用内存流,以确保垃圾回收知道发生了什么。使用(MemoryStreams=newMemoryStream()){ProtoBuf.Serializer.Serialize(s,state);//使用typeof(T).Name进行类型的半强制执行e安全。不是最好的,但它有效。返回新的StateDefinition(typeof(T).Name,s.ToArray());会员删除如转载请注明出处: