• 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         }
  • 相关阅读:
    Hibernate连接mysql数据库的配置
    opendaynight(karaf) 和 mininet测试openflow
    电信新势力,TIP/CORD能颠覆电信设备商吗?
    minnet sample
    ONIE
    升级Mininet自带的OpenvSwitch & 编译OpenvSwitch
    mininet test
    dpctl 命令实践
    白盒交换机
    Wedge 100-32X 100GbE Data Center Switch
  • 原文地址:https://www.cnblogs.com/AspDotNetMVC/p/2943221.html
Copyright © 2020-2023  润新知