Nbear讲解 之核心类 DynamicMethodFactory

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         }

 

 

你可能感兴趣的:(dynamic)