今天封装Protobuf封包时候遇到一个问题;

Protobuf的反序列化方法MergeFrom,是写在扩展类里的;c#拓展类

通过反射获取不到这个方法,就没法使用Type来泛型封装...

然而仔细一想,拓展类不也是类吗,直接反射获取拓展类方法好了;

在看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# 反射调用拓展类方法的更多相关文章

  1. java黑魔法-反射机制-02-通过Java反射调用其他类方法

    package com.aaron.reflect; import java.lang.reflect.Method; import java.lang.reflect.InvocationTarge ...

  2. python 反射调用

    因为目前在写一个python的项目,用到了Python的反射机制,所以做一下笔记,把写项目过程中的感悟记下来. 先简单介绍下Demo用到的函数: sys.path 是python的模块的路径集,是一个 ...

  3. Unity调用Android类方法

    Unity调用Android类方法 1.  添加Unity的classes.jar文件 创建一个Android工程AndroidUnityDemo. 由于Unity的版本不同,直接在Unity安装包文 ...

  4. C#如何反射出委托的签名,如何使用反射调用委托

    本文阐述C#中如何反射出委托的签名,假如我们有委托FooDelegate定义如下 delegate double FooDelegate (string param, bool condition); ...

  5. 外壳exe通过反射调用dll时

    外壳exe通过反射调用dll时,dll是 4.0的框架,外壳exe也需要编译成4.0的框架,如果dll本身有调用32位的dll,那么外壳exe也需要编译成32位. 调试时报的那个错,直接继续运行,不影 ...

  6. 从vs2010的UnitTestFramework类库提取私有方法反射调用的方法

    背景 年龄大点的程序员都知道在vs2010中创建单元测试非常的简单,鼠标定位在方法名字,右键创建单元测试,就会创建一个测试方法,即使是在私有方法上也可以创建测试方法. VS2010以后就没这么简单了, ...

  7. VS2010 F5调试时出现:“ 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常”解决

    VS2010 F5调试时出现 尝试运行项目时出错:未捕获通过反射调用的方法引发的异常 两个解决方法:1) 打开项目属性,选择调试选项卡,将“启用非托管代码调试”一项钩上.2) 打开项目属性,选择调试选 ...

  8. 反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性、字段),而不去使用Invoke方法)

    反射-优化及程序集等(用委托的方式调用需要反射调用的方法(或者属性.字段),而不去使用Invoke方法)   创建Delegate (1).Delegate.CreateDelegate(Type, ...

  9. 反射调用与Lambda表达式调用

    想调用一个方法很容易,直接代码调用就行,这人人都会.其次呢,还可以使用反射.不过通过反射调用的性能会远远低于直接调用——至少从绝对时间上来看的确是这样.虽然这是个众所周知的现象,我们还是来写个程序来验 ...

随机推荐

  1. js 让小数四舍五入保留两位小数的函数是?

    js 让小数四舍五入保留两位小数的函数是? 例子:data.relations[i].data[j].toFixed(2) toFixed(2)这个函数就是保留两位小数的作用

  2. 经验:使用mysqlimport快速导入csv文件

    mysqlimport 工具实际上也只是"load data infile"命令的一个包装实现.常用选项:--fields-terminated-by=字符串:设置字符串为字段之间 ...

  3. JAVA连接redis报错 :stop-writes-on-bgsave-error option

    (error) MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist o ...

  4. JAVA地址通过百度地图API转化为经纬度

    public static Map getLngAndLat(String address) { Map map = new HashMap(); String url = "http:// ...

  5. cmake之错误【Modules/ExternalProject.cmake:3206 (_ep_add_download_command)....】

    本文的 cmake的version是3.18 本文环境: Ubuntu 64 + CMAKE 3.18 错误描述 1.错误内容 Modules/ExternalProject.cmake:3206 ( ...

  6. 【LeetCode】295. Find Median from Data Stream 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 大根堆+小根堆 日期 题目地址:https://le ...

  7. hdu -4325-Flowers(离散化 线段树)

    http://acm.hdu.edu.cn/showproblem.php?pid=4325: 题目意思: 给你N个花开的时间段,然后在有M个时间点,问你在这个时间点有多少花开着. 昨天刚做的一个类似 ...

  8. 修改gorm支持protobuf

    gorm的功能很强大,支持很多很多特性,打算在项目中用上它. 但gorm不支持protobuf,如果idl用的是protobuf,需要对每个message做一个重新定义一个内部的struct,使得可以 ...

  9. Sentry 企业级数据安全解决方案 - Relay 入门

    内容整理自官方开发文档 Sentry Relay 通过提供作为应用程序和 sentry.io 之间中间层的独立服务来提供企业级数据安全性. Relay 专门设计用于: 在将个人身份信息 (PII) 发 ...

  10. Sentry 企业级数据安全解决方案 - Relay 运行模式

    内容整理自官方开发文档 Relay 可以在几种主要模式之一下运行,如果您正在配置 Relay server 而不是使用默认设置,那么事先了解这些模式至关重要. 模式存储在配置文件中,该文件包含 rel ...