網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
今天封裝Protobuf封包時(shí)候遇到一個(gè)問(wèn)題;
Protobuf的反序列化方法MergeFrom,是寫在擴(kuò)展類里的;
C# 類拓展方法
要求:
擴(kuò)展方法類必須為靜態(tài)類;
拓展方法必須為靜態(tài)方法,參數(shù)為this+需拓展類對(duì)象;
多個(gè)類拓展方法可以寫在一個(gè)拓展類中;
public class TestExtension { public string Test1() { return "test"; } } public static class MyExtension { public static void Show(this TestExtension obj) { Debug.Log("ExtensionFunc:"+ obj.Test1()); } }
調(diào)用:
TestExtension ts = new TestExtension(); ts.Show();
通過(guò)反射獲取不到這個(gè)方法,就沒(méi)法使用Type來(lái)泛型封裝...
然而仔細(xì)一想,拓展類不也是類嗎,直接反射獲取拓展類方法好了;
C#反射調(diào)用拓展類
在看Google.Protobuf源碼,找到這個(gè)類;
這個(gè)MergeFrom方法就是需要的;
那這個(gè)IMessage接口怎么辦;
所有自動(dòng)生成的protobuf類都只自動(dòng)繼承兩個(gè)接口;
所以傳需要序列化的類即可;
//接收到服務(wù)器消息;反序列化后執(zhí)行相應(yīng)路由方法 public void DispatchProto(int protoId, byte[] bytes) { if (!ProtoDic.ContainProtoId(protoId)) { Logger.LogError($"Unkown ProtoId:{protoId}"); return; } Type protoType = ProtoDic.GetProtoTypeByProtoId(protoId); Logger.Log($"protoId:{protoId};--typeName:{protoType.FullName}"); //打印傳輸獲得的字節(jié)的utf-8編碼 PrintUTF8Code(bytes); Type tp = typeof(Google.Protobuf.MessageExtensions); //反射獲取拓展類方法MergeFrom MethodInfo method = ReflectTool.GetExtentMethod(tp,"MergeFrom", protoType, typeof(byte[])); //反射創(chuàng)建實(shí)例,回調(diào)方法 object obj = ReflectTool.CreateInstance(protoType); ReflectTool.MethodInvoke(method, obj, obj, bytes); sEvents.Enqueue(new KeyValuePair<Type, object>(protoType, obj)); }
ProtoDic存儲(chǔ)了protoId和對(duì)應(yīng)的類型Type;
ReflectTool.GetExtentMethod——封裝了GetMethod方法,為了能連續(xù)傳入多個(gè)參數(shù),而不是傳Type數(shù)組;
ReflectTool.MethodInvoke——和上面目的一樣;
//獲取擴(kuò)展方法 public static MethodInfo GetExtentMethod(Type extentType, string methodName, params Type[] funcParams) { MethodInfo method = GetMethod(extentType, methodName, funcParams); return method; } public static object MethodInvoke(MethodInfo method, object obj, params object[] parameters) { return method.Invoke(obj, parameters); }
//通過(guò)Type創(chuàng)建實(shí)例,返回Object public static object CreateInstance(Type refType, params object[] objInitial) { object res = System.Activator.CreateInstance(refType, objInitial); if (res == null) { Logger.LogError($"Reflect create Type:{refType.FullName} is null"); } return res; }
最后寫測(cè)試代碼:
pb.BroadCast結(jié)構(gòu)為:
message BroadCast{ int32 PID =1; int32 Tp = 2; string Content = 3; }
運(yùn)行代碼:
Pb.BroadCast bo = new Pb.BroadCast(); bo.PID = 1; bo.Tp = 1; bo.Content = "Perilla"; byte[] res = bo.ToByteArray(); //打印字節(jié)的utf-8編碼 StringBuilder strBuilder = new StringBuilder(); for (int i = 0; i < res.Length; ++i) { strBuilder.Append(res[i]); strBuilder.Append('-'); } Logger.Log(strBuilder.ToString()); Pb.BroadCast bo2 = new Pb.BroadCast(); bo2.MergeFrom(res); Logger.LogFormat("{0}=={1}=={2}", bo2.PID, bo2.Tp, bo2.Content);
運(yùn)行結(jié)果:
總結(jié)?
原文鏈接:https://www.cnblogs.com/littleperilla/p/15830746.html
相關(guān)推薦
- 2022-09-25 MongoDB聚合管道 $lookup 與$mergeObjects配合使用 以及使用let,pip
- 2022-03-24 使用Redis如何設(shè)置永久有效_Redis
- 2022-08-23 多線程python的實(shí)現(xiàn)及多線程有序性_python
- 2022-10-10 C++淺析程序中內(nèi)存的分布_C 語(yǔ)言
- 2022-05-15 C++的數(shù)據(jù)共享與保護(hù)你了解嗎_C 語(yǔ)言
- 2022-08-13 Android開發(fā)Viewbinding委托實(shí)例詳解_Android
- 2022-07-29 C#?獲取數(shù)據(jù)庫(kù)中所有表名、列名的示例代碼_C#教程
- 2022-09-23 python人工智能自定義求導(dǎo)tf_diffs詳解_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支