C# 如何在.net中获取方法体的哈希?

C# 如何在.net中获取方法体的哈希?,c#,.net,C#,.net,我希望生成一个方法体或整个类的散列,以便将其与以前的散列进行比较,从而在运行时检测更改 我已经看到在单声道使用中实现了这一点 可以在Microsoft.NET中执行此操作吗?如果是,怎么做 或者你用过什么其他的方法 背景 我想将我的实体投影到一个只读的、非规范化的数据库中——如果您愿意,这是一种本地缓存 每当实体发生更改时,执行此操作的转换算法将被ping。然后,它将获取有问题的实体并生成投影。但是,在启动时或作为部署的一部分,我想检查转换算法是否已更改,如果已更改,则删除并重新生成表,然后使用

我希望生成一个方法体或整个类的散列,以便将其与以前的散列进行比较,从而在运行时检测更改

我已经看到在单声道使用中实现了这一点

可以在Microsoft.NET中执行此操作吗?如果是,怎么做

或者你用过什么其他的方法

背景

我想将我的实体投影到一个只读的、非规范化的数据库中——如果您愿意,这是一种本地缓存

每当实体发生更改时,执行此操作的转换算法将被ping。然后,它将获取有问题的实体并生成投影。但是,在启动时或作为部署的一部分,我想检查转换算法是否已更改,如果已更改,则删除并重新生成表,然后使用主存储中的所有实体重新填充它

我在Event Source/CQRS博客中看到过这种方法的建议,但如果您有其他/更好的方法来满足这一需求,请随时发表评论

基于Jon Skeet答案的不完整解决方案

以下LinqPad C#计划旨在实现这一点:

void Main()
{
    GetMethodHash(this.GetType(), "DoOriginal").Dump();
    GetMethodHash(this.GetType(), "DoSame").Dump();
    GetMethodHash(this.GetType(), "DoWithConstChange").Dump();
    GetMethodHash(this.GetType(), "DoWithCodeChange").Dump();
}

// Define other methods and classes here

private string DoOriginal(int data)
{
    return string.Format("data = {0}", data);
}

private string DoSame(int data)
{
    return string.Format("data = {0}", data);
}

private string DoWithConstChange(int data)
{
    return string.Format("data : {0}", data);
}

private string DoWithCodeChange(int data)
{
    return string.Format("data = {0} {1}", data, 999);
}

private string GetMethodHash(Type type, string methodName)
{
    var method = type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance );
    var body = method.GetMethodBody();
    var il = body.GetILAsByteArray();

    using (var sha256 = System.Security.Cryptography.SHA256.Create())
    {
        byte[] hash = sha256.ComputeHash(il);
        string hashBase64 = Convert.ToBase64String(hash);
        return string.Format("{0}{1}", methodName.PadRight(20), hashBase64);
    }
}
产出:

DoOriginal          +PyMqwv5PVz7/7EnNL9A676XNw/g8x2KfEUa63wD9oU=
DoSame              +PyMqwv5PVz7/7EnNL9A676XNw/g8x2KfEUa63wD9oU=
DoWithConstChange   VZX2CkxwUHzJVt8Tn73jmL1I5dKYUFKyD9bPwPsItVk=
DoWithCodeChange    9kZkq0fDHUXqxOmclwso/r2pQLDyNVwTtkIppSkcdQg=
我对此的第一次调查似乎在DoorOriginal和DowithConstantChange之间产生了相同的散列。。。但那是在午饭前,现在看起来还可以。所以要么是发生了一些奇怪的事情,要么是我需要休息——我投后者的票

下一步是添加引用的代码和结构。有什么建议吗?

您可以使用获取,然后根据您喜欢的内容(例如)使用您想要的任何类型的散列(例如SHA-256)创建散列


当然,IL有可能在不改变源代码的情况下改变(例如,由于编译器的改变),反之亦然(例如,如果局部变量名改变了,但在优化的IL中不存在)。

你是一个传奇!超级快速和清晰的答案。我认为,就这一目的而言,重要的是IL。如果它偶尔在不应该更改的时候更改,那么这很好——只要它不会在每次编译时更改。是时候进行一些原型设计了……我已经根据您的答案编辑了这个问题,并实现了一个。然而,它并不能完全适用于我想要检测的每一种代码更改。如果你有时间,请你看一下好吗?干杯,再次编辑,因为我一定错过了阅读我第一次尝试的结果,LinqPad有一个有用的工具来轻松检查IL。下一步是遵循依赖关系,但在这一点上,我开始认为手动更新版本属性会更简单,即使它确实依赖于程序员记住更新它。也许我可以使用Roslyn将散列注入一个基于(值得思考!)的属性中。@WooWaaBob:那么通过你的编辑,看起来一切都还可以吗?是的,谢谢Jon。当前的实现看起来似乎适用于此处列出的基本场景。乍一看就可以了,但我想我想看看通过遵循依赖关系,从而生成一个整体哈希,可以走多远。干杯,Rob您可以为方法定义版本属性,在对方法体本身进行更改时手动更改。另一种想法是尝试使用此方法来确定代码的更改是否会影响输出。的可能重复