.net Emit 动态创建类型之源代码级调试

长达N年的XXXXX工作终于结束,今天终于回归技术,特写此篇博文,开个好头
度娘竟然没有搜出一篇关于Emit动态创建类型调试相关的内容?
难道要用windbg?!!!!DbgClr在VS2010中也消失不见,疯了
果断问google,找到了一篇英文emit调试说明
原文见:http://blogs.msdn.com/b/jmstall/archive/2005/02/03/366429.aspx
为照顾英文小白和象我一样的半桶水,特写一篇中文emit调试方法:
1.引入以下命名空间:

using System.Diagnostics;
using System.Diagnostics.SymbolStore;
2.程序集按以下定义:

AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("xxxx"), AssemblyBuilderAccess.RunAndSave);
看到没,要RunAndSave,至少要Run


3.给动态程序集加入DebuggableAttribute特性:

//定义调试信息
CustomAttributeBuilder debugAttributeBuilder=new CustomAttributeBuilder(
typeof(DebuggableAttribute).GetConstructor(new Type[]{typeof(DebuggableAttribute.DebuggingModes)}),
new object[] {
DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.Default
}
);
assemblyBuilder.SetCustomAttribute(debugAttributeBuilder);


4.还要给模块定义加入:

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MastzouBase.DynamicProxy.Proxy.dll", "MastzouBase.DynamicProxy.Proxy.dll", true);//关键这里要true
ISymbolDocumentWriter DOC = moduleBuilder.DefineDocument(@"d:\IL的cs源代码片断在这里.txt", Guid.Empty, Guid.Empty, Guid.Empty);//要定义源代码位置,这个文档不需要全部源代码,只需要你想调试的il源代码翻译就可以了

5.好了,按照1,2,3,4你的程序集已经做好被调教的准备了,现在开始说具体怎么调

引用个例子"世界你好:
先写源代码d:\IL的cs源代码片断在这里.txt内容如下:
// Test
xyz = "hello";
Write(xyz);
return;
然后把源代码翻译成emit如下:
ILGenerator ilGenerator = methodbuilder.GetILGenerator(); //
LocalBuilder localXYZ = ilGenerator.DeclareLocal(typeof(string));
localXYZ.SetLocalSymInfo("xyz"); //看到没,设置下变量名,有助于调试
// Line 2: xyz = "hello";
ilGenerator.MarkSequencePoint(doc, 2, 0, 2, 100);//设置代码对应,意思是:下面IL代码对应的cs源代码所在的行和列,这里是第2行第0列开始,到第2行100列结束。注意行是从1开始算起,列是0开始算起。什么?为什么这里是2不是1,你没看到" d:\IL的cs源代码片断在这里.txt"文件中第一行是注释么!!!!为什么是100列结束?你高兴可以设置成200!!!
ilGenerator.Emit(OpCodes.Ldstr, "世界你好!");
ilGenerator.Emit(OpCodes.Stloc, localXYZ); //看到没?这就是设置变量名的好处,异读!!
// Line 3: Write(xyz);第二行对应结束了,这里是第3行的il代码
MethodInfo infoWriteLine = typeof(System.Console).GetMethod("WriteLine", newType[] { typeof(string) }); ilGenerator.MarkSequencePoint(doc, 3, 0, 3, 100);//设置代码对应,这不用再解释了吧!
ilGenerator.Emit(OpCodes.Ldloc, localXYZ);
ilGenerator.EmitCall(OpCodes.Call, infoWriteLine, null);
// Line 4: return;
ilGenerator.MarkSequencePoint(doc, 4, 0, 4, 100);//这不用再解释了吧!
ilGenerator.Emit(OpCodes.Ret);
好了代码对应也好了,现在方法也做好了被调教得准备了,所有调试准备都做完了
6。emit动态il源代码级调试!!!
用vs2010或者啥啥啥版本在工程打开d:\IL的cs源代码片断在这里.txt(不用把文件加入工程,当然如果你想,那也是可以的,好处是便于下次调试
打开后,你可以在其中随便设置断点,然后开调吧(注意不要破坏代码对应哦)
7。这个方法
不能调试emit发出的动态方法
,那咋调?等待我下个帖子吧,骚年!!

小提示:ildasm.exe加Reflector.exe你懂得,嘿嘿
全文结束,祝你好运,再见




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章