zoukankan      html  css  js  c++  java
  • 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         }
  • 相关阅读:
    windows 按时自动化任务
    Linux libusb 安装及简单使用
    Linux 交换eth0和eth1
    I.MX6 GPS JNI HAL register init hacking
    I.MX6 Android mmm convenient to use
    I.MX6 GPS Android HAL Framework 调试
    Android GPS GPSBasics project hacking
    Python windows serial
    【JAVA】别特注意,POI中getLastRowNum() 和getLastCellNum()的区别
    freemarker跳出循环
  • 原文地址:https://www.cnblogs.com/AspDotNetMVC/p/2943221.html
Copyright © 2011-2022 走看看