编程语言
首页 > 编程语言> > .Net RuntimeExplorer开发日志(九) IL to C# - LINQ与其它补完

.Net RuntimeExplorer开发日志(九) IL to C# - LINQ与其它补完

作者:互联网

  解析LINQ前,还需要解决一个障碍,那就是??这个符号,这是语法糖之一,它表示如果一个对象为null时就会使用??后面的值,而且它会频繁出现在LINQ语句中,不信你可以用reflector测试看看。在这里我自定义了两个新的IL代码ternay和ldnullorobj,前者是三目运算符,后者则是这个??符号的替代,这样在解析表达式之前优先解析自定义的新IL来达到更加简化的效果,通过将多个IL合并为新IL让代码的解析性和可读性大大的增加。

  LINQ主要是源于system.core.dll中System.Linq.Enumerable类中的扩展方法,这些个方法大部分都有一个lambda参数,而lambda方法则是由编译器自动生成的匿名方法,并在调用时以Func<T>形式来表达,而这个定义方法的类型一定有CompilerGenerated特性,那么在解析时对Func的构造函数进行标记,记录这个匿名方法的token,然后在输出方法参数时解析它,根据token去寻找方法。在这里有个难点,通常获取方法体有两个方法,一是在窗口左侧点击方法名时才载入方法体并解析显示在右侧窗口中,二是点击右侧窗口中的链接后左侧窗口按路径逐一加载最后主动选中目标方法,然后就变成了方法一那样显示了。如何才能命令远程对象获取方法体,但不会让左侧窗口树变化,也不会刷新右侧窗口内容,则是难点所在,为此,只能用代码模拟点击效果来加载方法路径,这样左侧窗口不会变化,并传送无效的IWriter对象,让右侧内容窗口输出失败。还有能够想到的事情,lambda方法并不止是一句语句,它可以是一大段代码,为了能够简化代码,这里从SubBlock中派生了一个LambdaBlock,将方法体引用存入这个对象中,待这个SubBlock被Write时再调用CSharpWriter来输出lambda方法及其参数。

各种BUG和补完:

  发现一个在反射上的难题,在显示方法的父类型时总无法显示类型中绑定的泛型实参,关键点在于List<int>与List<T>这两个类型的MetadataToken值是一样的,当用这个值再Module.ResolveType()时,返回的只是List<T>类型,这样就把T的实参丢int失了。特别是泛型的构造函数,因为构造函数是没有泛参的,但构造的类型却有,所以当new一个泛型类型时就只能显示T U V无法显示实参类型 ,这放到mmeta的层面上看就是方法的declaringType如果是个TypeSpec,该如何保存并能够通过反射再找回这个TypeSpec的问题。

  添加三个语法糖符号??=,而?. ?[]则是ternay的变形产物,因此从ternay派生出了新的自定义IL命令ldnullorldobj

  添加一个被遗忘的关键字lock,它也是语法糖之一,就是Monitor.Enter和Exit这两个方法的调用

  对事件方法进行缩写,例xxx+=new EventHandle(null,method)写成xxx+=method,其原则是MulticastDelegate派生的委托类型进行才会缩写

  修正单独的return语句无法显示问题

标签:补完,窗口,RuntimeExplorer,C#,LINQ,IL,类型,解析,方法
来源: https://www.cnblogs.com/ccddnet/p/14152895.html