.Net RuntimeExplorer开发日志(十) IL to C# - dynamic
C#博大精深的语法糖已经让我不寒而栗了,后面不知还有多少个新语法糖在等着。目前,解析的基本工作虽已完善,但因是靠特征来解析,而参考目标是VS的生成器,所以还会有大量未知的情况会造成解析错误,这只能靠时间来解决。
先详细说说dynamic的解析原理。System.Runtime.CompilerServices命名空间中CallSite<T>这个类型是创建的代理,这个类型的公开的构造函数只有一个,它只有一个CallSiteBinder类型的参数,通过编译器的代码来看,这个参数是通过Microsoft.CSharp.RuntimeBinder命名空间中Binder类型下的静态方法来创建的,这里有十多个方法,涵盖了dynamic所有的调用方式,通过判断编译器使用了哪个方法来判定动态调用的形式。重点特征是这些个静态方法的最后一个参数,这里记录了调用成员的约束,我们记录这些内容并保存进blockwriter的context中,等到找到有CompilerGenerated标记的静态字段赋值时翻出刚刚所保存的内容,成对的保存进全局,这时如果有(通常是下一句表达式)对此静态字段引用Target并Invoke操作时,就可以将其参数作为引用对象,并与保存的调用名称和约束整理显示。
目前writer的代码已经相当的混乱了,各种缓存和状态的叠加判断,尤其是上下文的继承关系处理起来相当复杂,由于没有写注释的习惯,以至于有些先前的内容我都有些看不懂了。dynamic的功能实现大概用了两周,这里有个无解的难题,变量或字段如果是动态类型,它的真实类型则为object,那么就要区别哪个object是dynamic还是普通的object类型,也就是说在解析时就要注出dynamic这个特性,这只有在writer时才能判定,无法倒置,只能先不管了。而接下来要做的就是隐藏不该显示的东西,CompilerGenerated类型字段的赋值操作,由于只有writer时才能判定对应的关系,所以必须writer一次才能缓存进全局,然后cancel掉显示的操作;还要隐藏IsEven功能判断的if块的一半,这里我选择了显示else,隐藏if。但是,经过简单测试后发现问题极大,这个项目目前为止已经一年多了,头一次出现与我所设想完全不一样的情况,重点在dynamic与操作符的结合,例如:dynamic dn=new xxx();dn[idx]+=(100*dm.M(10));这样的语句,迫使我又重新设计整个符号体系。
现在是1月20号早晨6点,一个通宵把这个没什么大用的dynamic完成了,而且经过测试也基本达到目的了,休息。
增加了对新对象简化成员赋值的处理,也就是new obj(){x=a,y=b};这样。在这里要注意的是不止是对字段的赋值,也可对属性set值,同时set又是特殊方法,这着实为难了几天
修正了在反射时无法通过访问器搜索到非公共属性或事件的问题
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号