DynamicMethodFactory的作用就像它的名字一样,构建动态的方法。

所产生的动态方法基于两种委托类型:分别对应实例方法和静态方法,下面重点说静态的动态方法。

1 public delegate object StaticDynamicMethodProxyHandler(object[] paramObjs);
2 public delegate object DynamicMethodProxyHandler(object ownerInstance, object[] paramObjs);

基于委托StaticDynamicMethodProxyHandler, 动态创建一个方法,用StaticDynamicMethodProxyHandler传进来的参数作为genericMethodInfo方法的参数进行调用。

传参数的工作由LoadParameters()方法完成,因为委托中参数是用objcet数组的形式传进来的,所以现在就要将object数组的对象按照genericMethodInfo方法中的参数列表进行类型转换,

然后加载到堆栈内。

 

 1    protected static StaticDynamicMethodProxyHandler DoGetStaticMethodDelegate(
 2             Module targetModule, 
 3             MethodInfo genericMethodInfo, 
 4             params Type[] genericParameterTypes)
 5         { 
 6 
 7             //Create a dynamic method proxy delegate used to call the specified methodinfo
 8             CodeGenerator gen = new CodeGenerator(targetModule);
 9             gen.BeginMethod("dm" + Guid.NewGuid().ToString("N"), typeof(StaticDynamicMethodProxyHandler));
10 
11             MethodInfo makeGenericMethodInfo = MakeMethodGeneric(genericMethodInfo, genericParameterTypes);
12             LoadParameters(gen, makeGenericMethodInfo.GetParameters(), true);//将StaticDynamicMethodProxyHandler委托传入的参数,转给genericMethodInfo方法调用
13             gen.Call(makeGenericMethodInfo);
14 
15             CastValueToObject(gen, makeGenericMethodInfo.ReturnType);
16 
17             return (StaticDynamicMethodProxyHandler)gen.EndMethod();
18         }

 

LoadParameters方法:out参数类型与ref参数类型的差别如下,
C#:  void ILStudy(out int abc,ref int acc,ref string[] aaa,out string[] ccc)
IL: void ILStudy([out] int32& abc,int32& acc,string[]& aaa,[out] string[]& ccc)
在这里注意区分
ParameterInfo[] pis 参数和gen.Ldarg(0)参数的差别:gen.Ldarg(0)是新定义的方法的参数,也就是所基于的委托的参数列表。
pis是当前动态方法里面所要调用的方法genericMethodInfo的参数列表。
 1       private static void LoadParameters(CodeGenerator gen, ParameterInfo[] pis, bool isMethodStatic)
 2         {
 3             Check.Require(gen, "gen");
 4 
 5             //gen.Ldarg所加载的是从委托那边定义的参数,即 object DynamicMethodProxyHandler(object ownerInstance, object[] paramObjs);
 6             //而ParameterInfo[] pis参数的作用,就是将委托中paramObjs,转化为pis所对应的参数类型,然后调用参数列表所对应的方法
 7             if (pis != null)
 8             {
 9                 for (int i = 0; i < pis.Length; ++i)
10                 {  //加载委托中参数 object[] paramObjs
11                     if (isMethodStatic)
12                     {
13                         gen.Ldarg(0);//Ldarg是针对产生gen的方法的上下文决定的,方法上下文有参数列表
14                     }
15                     else
16                     {  //实例方法 arg0 是this对象,所以第一个参数是arg1
17                         gen.Ldarg(1);
18                     }
19                     //将索引值 index 推送到堆栈上。
20                     gen.Ldc(i);
21 
22                     Type srcType = pis[i].ParameterType;
23                     string str = srcType.ToString();
24 
25                     //对比方法
26                    //IL: void ILStudy([out] int32& abc,int32& acc,string[]& aaa,[out] string[]& ccc)
27                    //C#:  void ILStudy(out int abc,ref int acc,ref string[] aaa,out string[] ccc)
28                     if (str.EndsWith("&"))
29                     {
30                         srcType = CommonUtils.GetType(str.Substring(0, str.Length - 1));
31                     }
32 
33                     if (str.EndsWith("&")) //ref or out param
34                     {
35                         if (srcType.IsValueType && (pis[i].Attributes & ParameterAttributes.Out) != ParameterAttributes.Out) //ref value param
36                         {  
37                             //根据object类型的指令:将数组第i个数据,取为object形式
38                             gen.Ldelem(typeof(object));
39                             gen.Unbox(srcType);
40                         }
41                         else
42                         {
43                             if (srcType.IsValueType && srcType != typeof(object)) //out value param
44                             {   
45                                 //先保存,srcType的初始类型
46                                 gen.LoadDefaultValue(srcType);
47                                 gen.Box(srcType);
48                                 gen.Stelem(typeof(object));
49 
50                                 if (isMethodStatic)
51                                 {
52                                     gen.Ldarg(0);
53                                 }
54                                 else
55                                 {
56                                     gen.Ldarg(1);
57                                 }
58                                 gen.Ldc(i);
59                                 gen.Ldelem(typeof(object));
60                                 gen.Unbox(srcType);
61                             }
62                             else //ref or out class param
63                             {
64                                 gen.Ldelema(typeof(object));
65                             }
66                         }
67                     }
68                     else
69                     {
70                         gen.Ldelem(typeof(object));
71                         //转为实际类型
72                         if (srcType.IsValueType)
73                         {
74                             gen.UnboxAny(srcType);
75                         }
76                         else if (srcType != typeof(object))
77                         {
78                             gen.Castclass(srcType);
79                         }
80                     }
81                 }
82             }
83         }

 

 

posted on 2013-03-16 15:53  极简  阅读(510)  评论(0编辑  收藏  举报