技术开发 频道

颠覆C#王权的“魔比斯环”



   读者可以不必管这些代码是什么意思,只要注意上面黑体字部分。C#编译器已经自动加入了调用ParentClass的构造方法的代码(.ctor()表示构造方法),这一行是去不掉的。找到问题所在,就意味着离成功又近了一步。从中间代码可以看出,如果不让C#编译器加上这行不就行了吗?但我又不能再设计一个C#编译器,因此,只能利用C#原来的编译器。

    根据上面所述,现在我只要解决一个问题即可,就是要利用C#编译器来改变C#的规则。这就要求不能使用C#的代码,而构造方法的代码必须直接使用中间语言来完成(并不是象编译器一样直接生成dll或exe)。

    这可真给我出了个难题。不过C#和.net framework的强大使用坚信一定有方法解决,只是我暂时没找到而已。
    由于大多数使用虚拟机的语言都支持反射功能,因此,我决定碰碰运气,看看是否能通过反射解决这个问题。在.net中有一个命名空间System.Reflection。看了一下其中的类,基本都是用来得到信息的(方法、属性、Assembly的信息),并没有写入信息的(就是写入IL)。当我快要绝望的时候,终于眼前一亮。在System.Reflection中又发现了一个Emit命名空间。Emit的中文含义是“发出”的意思,想到此,我的希望又重新燃起。于是上MSDN查了关于Emit的资料。MSDN上说Emit的主要功能就是通过C#语言绕过C#编译器直接向内存中写入IL,要当于从硬盘上读取IL一样。yeah,这正是我需要的。有了这个,就可以动态生成代理类了。而且速度和静态类是一样的。
    在Emit中提高了IL指令的全部映射。如下面的代码将直接用IL生成一个方法及其实现:

public delegate String MyMethod(String str); private void GenerateMethod() { Type[] argsType = { typeof(String) }; DynamicMethod dm = new DynamicMethod("MyMethod1", typeof(String), argsType, typeof(Form1).Module); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldstr, "hello:"); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(String).GetMethod("Concat", new Type[]{typeof(String), typeof(String)})); il.Emit(OpCodes.Ret); MyMethod myMethod = (MyMethod)dm.CreateDelegate(typeof(MyMethod)); MessageBox.Show(myMethod("my friends")); }
    在上面代码中主要有三个地方需要提一下:
    1. OpCodes包含了IL的所有的指令。如OpCodes.Ldstr表示将一个字符串压栈(每个方法都有一个操作栈),OpCodes.Call表示调用C#中的其他方法。
    2. DynamicMethod类可以建立动态的普通方法。如果想建立构造方法,可以使用ConstructorInfo。
    3.所有的IL代码都是通过ILGenerator的Emit方法写入内存的。

    Emit就象电影中的“魔比斯环”一样,可以很容易地突破C#的限制,从而穿越了C#世界,到达了另外一个MSIL世界。这将为我们实现另人振奋的功能提供了可能性。
0
相关文章