C#反射調用拓展類方法實例代碼
今天封裝Protobuf封包時候遇到一個問題;
Protobuf的反序列化方法MergeFrom,是寫在擴展類裡的;c#拓展類
C# 類拓展方法
要求:
擴展方法類必須為靜態類;
拓展方法必須為靜態方法,參數為this+需拓展類對象;
多個類拓展方法可以寫在一個拓展類中;
public class TestExtension { public string Test1() { return "test"; } } public static class MyExtension { public static void Show(this TestExtension obj) { Debug.Log("ExtensionFunc:"+ obj.Test1()); } }
調用:
TestExtension ts = new TestExtension(); ts.Show();
通過反射獲取不到這個方法,就沒法使用Type來泛型封裝…
然而仔細一想,拓展類不也是類嗎,直接反射獲取拓展類方法好瞭;
C#反射調用拓展類
在看Google.Protobuf源碼,找到這個類;
這個MergeFrom方法就是需要的;
那這個IMessage接口怎麼辦;
所有自動生成的protobuf類都隻自動繼承兩個接口;
所以傳需要序列化的類即可;
//接收到服務器消息;反序列化後執行相應路由方法 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}"); //打印傳輸獲得的字節的utf-8編碼 PrintUTF8Code(bytes); Type tp = typeof(Google.Protobuf.MessageExtensions); //反射獲取拓展類方法MergeFrom MethodInfo method = ReflectTool.GetExtentMethod(tp,"MergeFrom", protoType, typeof(byte[])); //反射創建實例,回調方法 object obj = ReflectTool.CreateInstance(protoType); ReflectTool.MethodInvoke(method, obj, obj, bytes); sEvents.Enqueue(new KeyValuePair<Type, object>(protoType, obj)); }
ProtoDic存儲瞭protoId和對應的類型Type;
ReflectTool.GetExtentMethod——封裝瞭GetMethod方法,為瞭能連續傳入多個參數,而不是傳Type數組;
ReflectTool.MethodInvoke——和上面目的一樣;
//獲取擴展方法 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); }
//通過Type創建實例,返回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; }
最後寫測試代碼:
pb.BroadCast結構為:
message BroadCast{ int32 PID =1; int32 Tp = 2; string Content = 3; }
運行代碼:
Pb.BroadCast bo = new Pb.BroadCast(); bo.PID = 1; bo.Tp = 1; bo.Content = "Perilla"; byte[] res = bo.ToByteArray(); //打印字節的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);
運行結果:
總結
到此這篇關於C#反射調用拓展類方法的文章就介紹到這瞭,更多相關C#反射調用拓展類內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C#使用反射機制實現延遲綁定
- C#值類型、引用類型、泛型、集合、調用函數的表達式樹實踐
- C#實現接口base調用示例詳解
- c# 在Emit代碼中如何await一個異步方法
- 關於.Net 6 添加NLog的方法