亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

反編譯.NET Core中的匿名方法IL

反編譯.NET Core中的匿名方法IL

C#
GCT1015 2023-07-22 16:24:18
我有這個方法public void Add(Action<Cursor> action){    // Decompile `action` to C#}在方法內部,我想將內部的匿名方法反編譯action 為 C# 代碼,或 C# 代碼的 AST 表示形式。我嘗試使用Mono.Ceciland ICSharpCode.Decompiler(來自ILSpy存儲庫),但我找不到反編譯匿名方法的方法,因為這兩個庫都要求您從物理位置加載程序集并通過類型圖搜索方法,這看起來非常復雜,尤其是在尋找匿名方法時。有沒有辦法使用該方法的 IL Byte 數組,并將其反編譯為 C#?public void Add(Action<Cursor> action){    var il = action.Method.GetMethodBody().GetILAsByteArray();    var ast = decompiler.DecompileIL(il); // Does such decompiler exist?}
查看完整描述

1 回答

?
天涯盡頭無女友

TA貢獻1831條經驗 獲得超9個贊

使用該ICSharpCode.Decompiler庫(來自ILSpy存儲庫),我能夠反編譯 lambda 方法。

像這樣

public void Add(Action<Cursor> action)

{

? ? // Get the assembly in which the lambda resides

? ? var asm = Assembly.GetCallingAssembly();

? ? var file = asm.Location;


? ? // Create a resolver (a callback for resolving referenced assemblies during decompilation)

? ? var resolver = new CustomAssemblyResolver(asm);

? ? // Create an instance of decompiler

? ? var decompiler = new CSharpDecompiler(file, resolver, new DecompilerSettings());


? ? // Get an "EntityHandle" instance for the lambda's underlying method

? ? var method = MetadataTokenHelpers.TryAsEntityHandle(action.Method.MetadataToken);?


? ? var ast = decompiler.Decompile(new List<EntityHandle>() { method.Value });

}

正如我所提到的,您CSharpDecompiler為實例提供了一個解析器 ( IAssemblyResolver),其任務是在反編譯過程中加載引用的程序集。


ICSharpCode.Decompiler有一個UniversalAssemblyResolver(源),它通過搜索文件系統中的公共文件夾來完成工作(它接收一個框架版本以知道在哪里搜索)。我不喜歡它,因為它假設太多并且需要太多信息(我并不總是知道運行時的框架或其他部分),因此我創建了自己的解析器,它遍歷程序集圖(從調用程序集開始)。


class CustomAssemblyResolver : IAssemblyResolver

{

? ? private Dictionary<string, Assembly> _references;


? ? public CustomAssemblyResolver(Assembly asm)

? ? {

? ? ? ? _references = new Dictionary<string, Assembly>();

? ? ? ? var stack = new Stack<Assembly>();

? ? ? ? stack.Push(asm);


? ? ? ? while (stack.Count > 0)

? ? ? ? {

? ? ? ? ? ? var top = stack.Pop();

? ? ? ? ? ? if (_references.ContainsKey(top.FullName)) continue;


? ? ? ? ? ? _references[top.FullName] = top;


? ? ? ? ? ? var refs = top.GetReferencedAssemblies();

? ? ? ? ? ? if (refs != null && refs.Length > 0)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? foreach (var r in refs)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? stack.Push(Assembly.Load(r));

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }


? ? ? ? ;

? ? }


? ? public PEFile Resolve(IAssemblyReference reference)

? ? {

? ? ? ? var asm = _references[reference.FullName];

? ? ? ? var file = asm.Location;

? ? ? ? return new PEFile(file, new FileStream(file, FileMode.Open, FileAccess.Read), PEStreamOptions.Default, MetadataReaderOptions.Default);

? ? }


? ? public PEFile ResolveModule(PEFile mainModule, string moduleName)

? ? {

? ? ? ? var baseDir = Path.GetDirectoryName(mainModule.FileName);

? ? ? ? var moduleFileName = Path.Combine(baseDir, moduleName);

? ? ? ? if (!File.Exists(moduleFileName))

? ? ? ? {

? ? ? ? ? ? throw new Exception($"Module {moduleName} could not be found");

? ? ? ? }

? ? ? ? return new PEFile(moduleFileName, new FileStream(moduleFileName, FileMode.Open, FileAccess.Read), PEStreamOptions.Default, MetadataReaderOptions.Default);

? ? }

}

我不知道這是否是適合所有用例的最佳方法,但它對我來說非常有效,至少到目前為止是這樣。


查看完整回答
反對 回復 2023-07-22
  • 1 回答
  • 0 關注
  • 218 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號