【发布时间】:2015-03-21 18:39:06
【问题描述】:
我试图在运行时检测某个类的方法的源代码是否已更改。基本上我检索方法体 (IL),用 md5 对其进行哈希处理并将其存储在数据库中。下次我检查方法时,我可以比较哈希值。
public class Changed
{
public string SomeValue { get; set; }
public string GetSomeValue()
{
return SomeValue + "add something";
}
public async Task<string> GetSomeValueAsync()
{
return await Task.FromResult(SomeValue + "add something");
}
}
我正在使用 Mono.Cecil 来检索方法主体:
var module = ModuleDefinition.ReadModule("MethodBodyChangeDetector.exe");
var typeDefinition = module.Types.First(t => t.FullName == typeof(Changed).FullName);
// Retrieve all method bodies (IL instructions as string)
var methodInstructions = typeDefinition.Methods
.Where(m => m.HasBody)
.SelectMany(x => x.Body.Instructions)
.Select(i => i.ToString());
var hash = Md5(string.Join("", methodInstructions));
这很好用,除了标记为异步的方法。每当我向 SomeValue 方法添加一些代码时,哈希值就会发生变化。每当我向 GetSomeValueAsync 方法添加一些代码时,哈希不会改变。有谁知道如何检测异步方法的方法体是否发生了变化?
【问题讨论】:
-
我建议您使用 IlSpy 查看应用程序,禁用 Display->Options->Decompile async 方法。在
async方法上完成了相当大的魔力(比如yield方法) -
异步方法有所不同。编译器会将其转换为状态机。请参阅this 了解更多信息。另外一点点谷歌搜索将有助于了解异步方法在内部是如何工作的。
-
你真的不需要 Cecil 来做这么简单的事情......你可以使用
GetMethodBody().GetILAsByteArray()/GetMethodBody().LocalVariables -
@xanatos 那只会给出局部变量,我想知道方法体是否发生了变化,例如是否添加或更改了代码行。
-
IL作为字节数组,只给出方法中使用的操作码,不包括字符串等
标签: c# async-await il mono.cecil