分享
 
 
 

Reflector: Get the secret inside .NET assemblies.

王朝c#·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

本专题主要介绍Allen Lee在平时的工作和学习中遇到的好的.NET工具,并讲述相关的使用经验。工欲善其事,必先利其器。那么,现在就让我们看看有什么器可以利吧!

2. 在.NET上编程的朋友应该知道ILDASM的大名吧,这里为大家介绍另一个叫作Reflector的好东东。为了了解Reflector,我特意写了一个代码片断(这里只给出用C#写的Main方法的代码):

static void Main(string[] args)

{

ArrayList argList = new ArrayList();

if(args.Length != 0)

{

foreach(string arg in args)

{

switch(arg)

{

case "IL":

Console.WriteLine("IL");

argList.Add("IL");

break;

case "C#":

Console.WriteLine("C#");

argList.Add("C#");

break;

case "VB.NET":

Console.WriteLine("VB.NET");

argList.Add("VB.NET");

break;

case "Delphi":

Console.WriteLine("Delphi");

argList.Add("Delphi");

break;

default:

Console.WriteLine("Invalid Option");

break;

}

}

}

else

{

string choice = Console.ReadLine();

switch(choice)

{

case "IL":

Console.WriteLine("IL");

break;

case "C#":

Console.WriteLine("C#");

break;

case "VB.NET":

Console.WriteLine("VB.NET");

break;

case "Delphi":

Console.WriteLine("Delphi");

break;

default:

Console.WriteLine("Invalid Option");

break;

}

}

foreach(object obj in argList)

Console.WriteLine((string)obj);

}

对上面的代码进行编译,得到一个ReflectorLab.exe的程序集(Assembly),程序集的名字可能不同。然后我们运行Reflector,一开始它的界面是:

接着,我们打开菜单:File|Open,找到并选择刚刚编译的程序集,该程序集将会被加入到程序集列表,打开ReflectorLab的树,找到Main(string[]):Void这个方法,右击并选择Disassembler,将会得到下图的反编译代码:

现在截取反编译后的Main方法完整代码如下:

private static void Main(string[] args)

{

string text1;

object obj1;

string[] textArray1;

int num1;

string text3;

IEnumerator enumerator1;

IDisposable disposable1;

ArrayList list1 = new ArrayList();

if (args.Length != 0)

{

textArray1 = args;

num1 = 0;

while ((num1 < textArray1.Length))

{

text1 = textArray1[num1];

text3 = text1;

if (text3 == null)

{

goto Label_00CD;

}

text3 = string.IsInterned(text3);

if (text3 != "IL")

{

if (text3 == "C#")

{

goto Label_0085;

}

if (text3 == "VB.NET")

{

goto Label_009D;

}

if (text3 == "Delphi")

{

goto Label_00B5;

}

goto Label_00CD;

}

Console.WriteLine("IL");

list1.Add("IL");

goto Label_00D9;

Label_0085:

Console.WriteLine("C#");

list1.Add("C#");

goto Label_00D9;

Label_009D:

Console.WriteLine("VB.NET");

list1.Add("VB.NET");

goto Label_00D9;

Label_00B5:

Console.WriteLine("Delphi");

list1.Add("Delphi");

goto Label_00D9;

Label_00CD:

Console.WriteLine("Invalid Option");

Label_00D9:

num1 += 1;

}

goto Label_017C;

}

string text4 = Console.ReadLine();

if (text4 == null)

{

goto Label_0170;

}

text4 = string.IsInterned(text4);

if (text4 != "IL")

{

if (text4 == "C#")

{

goto Label_014C;

}

if (text4 == "VB.NET")

{

goto Label_0158;

}

if (text4 == "Delphi")

{

goto Label_0164;

}

goto Label_0170;

}

Console.WriteLine("IL");

goto Label_017C;

Label_014C:

Console.WriteLine("C#");

goto Label_017C;

Label_0158:

Console.WriteLine("VB.NET");

goto Label_017C;

Label_0164:

Console.WriteLine("Delphi");

goto Label_017C;

Label_0170:

Console.WriteLine("Invalid Option");

Label_017C:

enumerator1 = list1.GetEnumerator();

try

{

while (enumerator1.MoveNext())

{

obj1 = enumerator1.Current;

Console.WriteLine(((string) obj1));

}

}

finally

{

disposable1 = (enumerator1 as IDisposable);

if (disposable1 != null)

{

disposable1.Dispose();

}

}

}

反编译的代码在功能效果上与原代码是相同的,但是个人认为翻编译的代码的风格却不怎么棒,尤其是充满goto语句,乍一看我真得昏了过去。代码把原来的switch block全换成if block,将foreach block全换成while。我猜是因为它是从IL那里翻译出来的,而IL就是一门基于堆栈的语言,在IL里面没有流程控制语句,全部使用goto + Label模拟,于是得到这样的结果。

除此之外,我还发现一些很特别的东西,请留意这一句:text3 = string.IsInterned(text3); 它其实反映了.NET的字符串处理方式,使用了一种叫做字符串驻留(String Interning)的技术,该技术是为了减轻字符串的操作为系统带来的性能损失,详细解释请参见《Microsoft .NET框架程序设计(修订版)》的262页。另外我们看到原代码最后的foreach被翻译成一个try...finally block,在try里面实现foreach的功能,然后再finally里面自动为每一个enumerator试着调用IDisposable接口来释放资源,真是想得周到相信对应的IL也会有同样的“设施”,如果你懂IL的话,而你又肯定在这里不需要这样一个finally的话,你可以手动优化一下,呵呵。

翻译后的代码是有点复杂和混乱,不过,你可以从中窥探.NET的(部分)运行机制(而这种窥探原本是应该使用IL的),并了解到简单的C#代码背后,编译器在默默地为我们作了不少的工作!最后,我们还会惊喜地发现,Reflector不但支持反汇编成C#,还支持IL、VB.NET、Delphi,这下子爽了,我们可以比较并学习这些语言,以前我们用ILDASM来反汇编C#写的程序来学习IL,现在我们可以用Reflector反汇编C#写的程序来学习VB.NET和Delphi啦!当然,由于篇幅的问题,我不可以再往里面灌水(依次加入IL、VB.NET、Delphi反编译的代码)。

另外,你会发现这些源代码的某些地方,通常是类型名称或者方法名称又或者属性会是一个连接,按下去看看有什么事发生!是不是连接到该东西(类型或者方法或者属性)的.NET基类库的反编译代码上了?

最后,在文章的结束,我还有一个惊喜给你,就是Reflector本身是一个.NET程序,这意味着它还可以反汇编它自己,不幸试试看!

噢,补充一点,当你运行Reflector后,它会在它所在的文件夹会生成一个叫Reflector.cfg的文件,这个不是XML文件,是一种INI格式的配置文件,请留意该文件的[AssemblyLoader]区段,有什么发现了没有?好了,这次的介绍就到此为止,希望你发现更多的东西来跟我分享!

可以问你一个问题吗?当你看完这篇介绍后,你有没有想过使用这个工具?有多想?能给我一个回复么?(完全没兴趣、感觉无所谓、有机会可以一试、马上去下载一个看看)谢谢!

Allen Lee

See also:

NDoc: Make good use of your XML Comments

PINVOKE.NET: Do interop the wiki way!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有