• 使用Emit动态调用方法(技术原型)


        上周五快下班时,看到一个博友BillGan文章:DynamicMethod (JIT Compiler encountered an internal limitation. )我还是相信中国人 ,当时没有太多时间,只是实现了调用静态方法的访问,不能称为动态方法调用。今天看到,BillGan好像已经死心了。

         不过,其实没有那么绝望的吧,我实现了一个原型,原理是使用Emit声明一个变量,然后强制类型转化成类型,最后再去调用方法:

    代码
    1 using System;
    2  using System.Collections.Generic;
    3 using System.Linq;
    4 using System.Text;
    5 using System.Reflection.Emit;
    6 using System.Reflection;
    7 using Evlon.Util.Dynamic;
    8
    9 namespace ConsoleApplication2008
    10 {
    11 public class Program
    12 {
    13 static void Main(string[] args)
    14 {
    15 decimal ret = new Program().Dynamic("HelloWorld", Guid.NewGuid(), 2009);
    16 Console.WriteLine(ret);
    17
    18 Console.ReadLine();
    19 }
    20
    21 public decimal HelloWorld(Guid userId, int year)
    22 {
    23 return userId.GetHashCode() + year;
    24 }
    25 }
    26
    27 }
    28 namespace Evlon.Util.Dynamic
    29 {
    30 public static class TypeExtension
    31 {
    32 public static decimal Dynamic(this object inst, string methodName, Guid userId, int year)
    33 {
    34 Type instType = inst.GetType();
    35 Type[] paramTypes = new Type[] { typeof(object), typeof(Guid), typeof(int) };
    36 Type[] paramMethodTypes = new Type[] { typeof(Guid), typeof(int) };
    37 var dynamicMethod = new DynamicMethod("", typeof(decimal), paramTypes, true);
    38 MethodInfo stringMethod = inst.GetType().GetMethod(methodName, paramMethodTypes);
    39
    40 var ilGen = dynamicMethod.GetILGenerator();//IL生成器
    41
    42 //声明变量
    43 ilGen.DeclareLocal(instType);
    44
    45
    46 //把参数推到堆栈上
    47 ilGen.Emit(OpCodes.Ldarg_0);
    48
    49 //把参数1转化成指定的类型
    50 ilGen.Emit(OpCodes.Castclass, instType);
    51 ilGen.Emit(OpCodes.Stloc_0);
    52
    53 //加载参数
    54 ilGen.Emit(OpCodes.Ldloc_0);
    55 ilGen.Emit(OpCodes.Ldarg_1);
    56 ilGen.Emit(OpCodes.Ldarg_2);
    57
    58 //调用方法
    59 ilGen.Emit(OpCodes.Callvirt, stringMethod);
    60 ilGen.Emit(OpCodes.Ret);//结束并返回值
    61
    62 //生成委托
    63 Func<object, Guid, int, decimal> gan = (Func<object, Guid, int, decimal>)dynamicMethod.CreateDelegate(typeof(Func<object, Guid, int, decimal>));
    64
    65 //调用委托返回结果
    66 return gan(inst, userId, year);
    67 }
    68
    69 }
    70 }
    71
  • 相关阅读:
    Java控制台常用命令
    redis如何查看所有的key
    An internal error has occurred. Java heap space
    redis演练
    各种编程实现的树
    MYSQL两个数据库字符集保持一致问题
    进程控制之fork函数
    进程控制之进程标识符
    进程环境之getrlimit和setrlimit函数
    进程环境之setjmp和longjmp函数
  • 原文地址:https://www.cnblogs.com/evlon/p/1623025.html
Copyright © 2020-2023  润新知