如何检测异步方法体中的源代码更改

Rob*_*aap 0 c# il mono.cecil async-await

我试图在运行时检测类方法的源代码是否已更改。基本上,我检索方法主体 (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");
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用 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));
Run Code Online (Sandbox Code Playgroud)

除了标记为异步的方法之外,这非常有效。每当我向 SomeValue 方法添加一些代码时,哈希值就会发生变化。每当我向 GetSomeValueAsync 方法添加一些代码时,哈希值都不会更改。有谁知道如何检测异步方法的方法体是否已更改?

Rob*_*aap 5

我找到了一个解决方案,感谢@xanatos 和@Wormbo,他们为我指明了正确的方向。

对于异步方法,C# 编译器会生成一个包含方法主体的帮助程序类。这些辅助类可以在主类型的 NestedTypes 属性中找到。因此,如果我们包含嵌套类型的方法体,我们就可以创建正确的哈希:

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 nestedMethodInstructions = typeDefinition.NestedTypes
    .SelectMany(x=>x.Methods)
    .Where(m => m.HasBody)
    .SelectMany(x => x.Body.Instructions)
    .Select(i => i.ToString());


Md5(string.Join("", methodInstructions) + string.Join("", nestedMethodInstructions));
Run Code Online (Sandbox Code Playgroud)