• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

业余清洁工

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

.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你懂得,嘿嘿

全文结束,祝你好运,再见 

 

 

 

posted on 2012-07-23 13:26  业余清洁工  阅读(707)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3