Breck Fresen
Breck Fresen

Reputation: 295

Compute hash of class code at runtime (C#)?

Is it possible to compute the hash of a class at runtime in C# (presumably through reflection)? To be clear, I don't want to compute the hashcode of an instance of said class, I want to compute the hash of the class code itself (if a function in the class changes, I'd expect a different hash code to be computed). Ideally this would only be sensitive to changes in the object code (and not just a hash of the string representation of the code itself).

Thanks in advance for your help,

-- Breck

Upvotes: 9

Views: 1789

Answers (3)

Master DJon
Master DJon

Reputation: 1965

I know this question is old, but I wanted to share my HashClassCalculator that gives an hash of the code of all methods and properties. So, if anything change in those, the hash will change.

internal static class HashClassCalculator
{
    private static Dictionary<Type, string> hashes = new ();
    private static object lockingObject = new ();

    /// <summary>
    /// Calculate an hash of the code for a specific type
    /// </summary>
    /// <param name="type">Type to hash the code</param>
    /// <returns>MD5 hash of the class code</returns>
    /// <remarks>Thread protected + Cached for faster access</remarks>
    public static string CalculateHash(Type type)
    {
        if (hashes.ContainsKey(type)) return hashes[type]; // Fast return

        var currentHash = "";
        lock (lockingObject)
        {
            if (hashes.ContainsKey(type)) return hashes[type]; // Fast return

            var allFlag = System.Reflection.BindingFlags.Public
                | System.Reflection.BindingFlags.NonPublic
                | System.Reflection.BindingFlags.Instance
                | System.Reflection.BindingFlags.Static;
            var hasher = MD5.Create();

            // Get all properties hashes
            var props = type.GetProperties(allFlag);
            foreach (var prop in props)
            {
                var hashBytes = hasher.ComputeHash(prop.GetMethod.GetMethodBody().GetILAsByteArray());
                currentHash += Convert.ToBase64String(hashBytes); // Concatenate all the hashes
            }

            // Get all methods hashes
            var methods = type.GetMethods(allFlag);
            foreach (var method in methods)
            {
                if (method.DeclaringType != type) continue;

                var hashBytes = hasher.ComputeHash(method.GetMethodBody().GetILAsByteArray());
                currentHash += Convert.ToBase64String(hashBytes); // Concatenate all the hashes
            }

            // Hashing all hashes into one smaller
            var hashOfHashes = hasher.ComputeHash(Encoding.ASCII.GetBytes(currentHash));
            currentHash = Convert.ToBase64String(hashOfHashes);

            // Add to cache
            hashes.Add(type, currentHash);
        }

        return currentHash;
    }
}

Upvotes: 0

Andrew Bezzub
Andrew Bezzub

Reputation: 16032

You don't need to use reflection. You can try System.Type.GetHashCode(). I'm not sure how it works, if not optimal, than you can always use type.FullName.GetHashCode()

Upvotes: -1

Brian Rasmussen
Brian Rasmussen

Reputation: 116421

If you have the Type you can use GetMethod to get an instance of MethodInfo, which in turn has a GetMethodBody that returns the IL for said method. You can then hash that.

I am curious. Why do you want to do this in the first place?

Upvotes: 11

Related Questions