服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#反射调用拓展类方法实例代码

C#反射调用拓展类方法实例代码

2022-12-21 14:22小紫苏 C#

这篇文章主要给大家介绍了关于C#反射调用拓展类方法的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

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

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

C# 类拓展方法

要求:

扩展方法类必须为静态类;

拓展方法必须为静态方法,参数为this+需拓展类对象;

多个类拓展方法可以写在一个拓展类中;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TestExtension
{
    public string Test1()
    {
        return "test";
    }
}
 
public static class MyExtension
{
    public static void Show(this TestExtension obj)
    {
        Debug.Log("ExtensionFunc:"+ obj.Test1());
    }
}

调用:

?
1
2
TestExtension ts = new TestExtension();
ts.Show();

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

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

C#反射调用拓展类

在看Google.Protobuf源码,找到这个类;

C#反射调用拓展类方法实例代码

这个MergeFrom方法就是需要的;

那这个IMessage接口怎么办;

所有自动生成的protobuf类都只自动继承两个接口;

C#反射调用拓展类方法实例代码

所以传需要序列化的类即可;

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//接收到服务器消息;反序列化后执行相应路由方法
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——和上面目的一样;

?
1
2
3
4
5
6
7
8
9
10
11
//获取扩展方法
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);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
//通过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结构为:

?
1
2
3
4
5
message BroadCast{
    int32 PID =1;
    int32 Tp = 2;
    string Content = 3;       
}

运行代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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#反射调用拓展类方法的文章就介绍到这了,更多相关C#反射调用拓展类内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/littleperilla/p/15830746.html

延伸 · 阅读

精彩推荐
  • C#如何利用Jenkins + TFS为.Net Core实现持续集成/部署详解

    如何利用Jenkins + TFS为.Net Core实现持续集成/部署详解

    这篇文章主要给大家介绍了关于如何利用Jenkins + TFS为.Net Core实现持续集成/部署的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具...

    myzony4372022-02-23
  • C#C#使用yield关键字构建迭代器详解

    C#使用yield关键字构建迭代器详解

    这篇文章主要为大家详细介绍了C#使用yield关键字构建迭代器的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    绛河7402022-01-24
  • C#Unity Shader实现动态雾效果

    Unity Shader实现动态雾效果

    这篇文章主要为大家详细介绍了Unity Shader实现动态雾效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    ZzEeRO9652022-09-05
  • C#C#语言中字符类char的使用方法(总结)

    C#语言中字符类char的使用方法(总结)

    下面小编就为大家带来一篇C#语言中字符类char的使用方法(总结)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7702021-12-30
  • C#C#连接加密的Sqlite数据库的方法

    C#连接加密的Sqlite数据库的方法

    对数据加密分两种,一种是对数据库本身进行加密,另一种是对数据表中的数据进行加密,下面通过本文给大家介绍C#连接加密的Sqlite数据库的方法,感兴...

    LittleFeiHu11962022-01-19
  • C#unity使用socket实现聊天室功能

    unity使用socket实现聊天室功能

    这篇文章主要为大家详细介绍了unity使用socket实现聊天室功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    ai上白菜9332022-11-07
  • C#细说C#中的枚举:转换、标志和属性

    细说C#中的枚举:转换、标志和属性

    枚举是 C# 中最有意思的一部分,大部分开发人员只了解其中的一小部分,甚至网上绝大多数的教程也只讲解了枚举的一部分。那么,我将通过这篇文章向大...

    朱钢11572022-08-27
  • C#C#实现类似jQuery的方法连缀功能

    C#实现类似jQuery的方法连缀功能

    这篇文章主要介绍了C#实现类似jQuery的方法连缀功能,可以简化语句,使代码变得清晰简单,感兴趣的小伙伴们可以参考一下...

    JackWang-CUMT4762021-11-02