源码发布 - DynamicMethodProxyFactory组件
在前面的文章改进的“以非泛型方式调用泛型方法”之基于DynamicMethod的实现中,提到了一种通过DynamicMethod以非泛型方法代理访问泛型方法的较佳方法(无额外代码定义需要,执行时间大约相当于直接调用泛型方法的3-4倍)。本文介绍的组件在前文思路的基础上,进行进一步的扩展,封装成一个较通用的DynamicMethodProxyFactory组件。除了可以较高性能访问任意的静态或非静态、泛型或非泛行方法之外,利用DynamicMethod可将代码插入内存中已载入的Module的能力,提供了在程序集外实例化指定Module中的internal类型,在程序集外调用internal类型的方法和public类型的internal方法的支持。
该组件实现如下功能:
1、以通用的非泛行方法Delegate访问任意方法(泛型或非泛型,静态或非静态);
2、支持在程序集外调用指定Module中的internal类型的任意属性(属性本质上可以通过它的get/set方法以方法的形式访问)和方法和public类型的internal方法;
3、支持创建并返回指定Module中的internal类型的实例;
以非泛型方式调用泛型方法的意义在前文中已经讨论过了,对很多支持泛型方法的框架来说,是非常必要的代替反射的功能(相比反射性能提升3-4个数量级)。
那么访问internal类型和方法有什么意义呢?除了突破原来的CLR的不能跨程序集访问internal成员的限制这个明显的好处之外,更大的意义在于我们可以使用.Net Framework提供的很多非常有用的internal组件,这些组件,MS出于各种原因标记为了internal,但是,既然提供了,我们就有理由去使用它,对于实现我们自己的组件时充分利用.Net Framework内置的这些组件而减少我们重复劳动的工作量也很有意义。
使用演示:
下载测试代码和类库源码
该组件实现如下功能:
1、以通用的非泛行方法Delegate访问任意方法(泛型或非泛型,静态或非静态);
2、支持在程序集外调用指定Module中的internal类型的任意属性(属性本质上可以通过它的get/set方法以方法的形式访问)和方法和public类型的internal方法;
3、支持创建并返回指定Module中的internal类型的实例;
以非泛型方式调用泛型方法的意义在前文中已经讨论过了,对很多支持泛型方法的框架来说,是非常必要的代替反射的功能(相比反射性能提升3-4个数量级)。
那么访问internal类型和方法有什么意义呢?除了突破原来的CLR的不能跨程序集访问internal成员的限制这个明显的好处之外,更大的意义在于我们可以使用.Net Framework提供的很多非常有用的internal组件,这些组件,MS出于各种原因标记为了internal,但是,既然提供了,我们就有理由去使用它,对于实现我们自己的组件时充分利用.Net Framework内置的这些组件而减少我们重复劳动的工作量也很有意义。
使用演示:
1
using System;
2
using System.Collections.Generic;
3
using System.Reflection;
4
using System.Reflection.Emit;
5
using System.Text;
6
7
namespace DynamicMethodProxyTest
8
{
9
public class Program
10
{
11
//用于测试的静态方法
12
public static void Add<T>(T obj, IList<T> list)
13
{
14
//list.Add同时也是用于测试的非静态方法
15
list.Add(obj);
16
}
17
18
private const int REPEAT_TIME = 20000000;
19
20
static void Main(string[] args)
21
{
22
//创建一个内置缓存支持的DynamicMethodProxyFactory实例
23
NBear.DynamicMethodHelper.DynamicMethodProxyFactory fac = new NBear.DynamicMethodHelper.CachableDynamicMethodProxyFactory();
24
25
//创建一个internal的System.Web.HttpDictionary类实例
26
Console.WriteLine("Create an instance of internal type - System.Web.HttpDictionary.");
27
object temp = fac.CreateInstance(typeof(System.Web.HttpApplication).Module, "System.Web.HttpDictionary", false, false);
28
29
//创建访问该实例的SetValue和GetValue方法的DynamicMethosProxyDelegate
30
Console.WriteLine("Create DynamicMethodProxyDelegate of HttpDictionary's SetValue and GetValue methods.");
31
NBear.DynamicMethodHelper.DynamicMethodProxyDelegate setDelegate = fac.GetMethodDelegate(typeof(System.Web.HttpApplication).Module, temp.GetType().GetMethod("SetValue", BindingFlags.NonPublic | BindingFlags.Instance));
32
NBear.DynamicMethodHelper.DynamicMethodProxyDelegate getDelegate = fac.GetMethodDelegate(typeof(System.Web.HttpApplication).Module, fac.GetMethodInfoBySignature(temp.GetType(), "System.Object GetValue(System.String)", false, false));
33
34
//在该实例上 Set & Get 测试数据
35
Console.WriteLine("set \"test value\" on the internal type instance");
36
setDelegate(temp, "test", "test value");
37
Console.WriteLine("get the test value from the internal type instance: " + getDelegate(temp, "test"));
38
39
//测试DynamicMethodProxyDelegate的性能
40
Console.WriteLine("Test the performance of DynamicMethodProxyDelegate.");
41
List<int> list = new List<int>();
42
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
43
watch.Reset();
44
watch.Start();
45
for (int i = 0; i < REPEAT_TIME; i++)
46
{
47
//这里是直接泛型调用
48
Program.Add<int>(i, list);
49
}
50
watch.Stop();
51
long l1 = watch.ElapsedMilliseconds;
52
watch.Reset();
53
MethodInfo mi = typeof(Program).GetMethod("Add");
54
//创建一个静态方法的StaticDynamicMethodDelegate
55
NBear.DynamicMethodHelper.StaticDynamicMethodProxyDelegate sdmd = fac.GetStaticMethodDelegate(mi, typeof(int));
56
watch.Start();
57
for (int i = 0; i < REPEAT_TIME; i++)
58
{
59
//通过StaticDynamicMethodDelegate以非泛型方式访问泛型方法
60
sdmd(i, list);
61
}
62
watch.Stop();
63
long l2 = watch.ElapsedMilliseconds;
64
watch.Reset();
65
MethodInfo mi2 = list.GetType().GetMethod("Add");
66
//创建一个DynamicMethodDelegate访问同样的Add方法
67
NBear.DynamicMethodHelper.DynamicMethodProxyDelegate dmd = fac.GetMethodDelegate(mi2);
68
watch.Start();
69
for (int i = 0; i < REPEAT_TIME; i++)
70
{
71
//通过DynamicMethodDelegate访问
72
dmd(list, i);
73
}
74
watch.Stop();
75
long l3 = watch.ElapsedMilliseconds;
76
Console.WriteLine("{0}\nDirectly vs Static vs Non-static\n{1} vs {2} vs {3}", list.Count, l1, l2, l3);
77
Console.ReadLine();
78
}
79
}
80
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

下载测试代码和类库源码
分类:
NBear
, Tech. Thinking
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异