How can I get a hash of the body of a method in .net?

I'd like to generate a hash of a method body or entire class in order to compare it to a previous hash and therefore detect changes at run-time.

I've seen reference to this being achieved in Mono using Mono.Cecil.

Is it possible to do this in Microsoft.NET? If so how?

Or what other approaches have you used?

Background

I'd like to create projections of my entities into a read-only, denormalised database - a kind of local cache if you like.

The transformation algorithm that does this will be pinged whenever a change has occurred to the entities. It will then take the entity in question and generate the projection. However, on start up or as part of the deployment, I'd like to check if the transformation algorithm has changed and if so delete and regenerate the table and then repopulate it using all the entities in the main store.

I've seen this approach suggested in Event Source/CQRS blogs but feel free to comment if you have alternative/better approaches to this requirement.

Incomplete Solution based on Jon Skeet's Answer

The following LinqPad C# Program is an attempt at implementing this:

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);
    }
}

Outputs:

DoOriginal          +PyMqwv5PVz7/7EnNL9A676XNw/g8x2KfEUa63wD9oU=
DoSame              +PyMqwv5PVz7/7EnNL9A676XNw/g8x2KfEUa63wD9oU=
DoWithConstChange   VZX2CkxwUHzJVt8Tn73jmL1I5dKYUFKyD9bPwPsItVk=
DoWithCodeChange    9kZkq0fDHUXqxOmclwso/r2pQLDyNVwTtkIppSkcdQg=

My first investigation with this appeared to produce the same hash between DoOriginal and DoWithConstChange ... but that was before lunch and now it looks okay. So either something odd was going on or I needed the break - I vote the latter.

Next up would be to add in referenced code and structures. Any suggestions?

Jon Skeet
people
quotationmark

You can use MethodInfo.GetMethodBody() to get a MethodBody, then create a hash based on whatever you like (e.g. the IL byte array) using whatever kind of hash you want (e.g. SHA-256).

Of course, it's possible for the IL to change without the source code changing (e.g. due to changing compiler) - or vice versa (e.g. if a local variable name was changed but not present in the optimized IL).

people

See more on this question at Stackoverflow