For various reasons, I need to implement a type caching mechanism in C#. Fortunately, the CLR provides Type.GUID
to uniquely identify a type. Unfortunately, I can't find any way to look up a type based on this GUID. There's Type.GetTypeFromCLSID()
but based on my understanding of the documentation (and experiments) that does something very, very different.
Is there any way to get a type based on its GUID short of looping through all the loaded types and comparing to their GUIDs?
EDIT: I forgot to mention that I would really like a "type fingerprint" of fixed width, that's why the GUID is so appealing to me. In a general case, of course, the fully qualified name of the type would work.
This may just be a summary of answers already posted, but I don't think there is a way to do this without first building a map of Guid->Type.
We do this in our framework on initialization:
static TypeManager()
{
AppDomain.CurrentDomain.AssemblyLoad += (s, e) =>
{
_ScanAssembly(e.LoadedAssembly);
};
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
{
_ScanAssembly(a);
}
}
private static void _ScanAssembly(Assembly a)
{
foreach (Type t in a.GetTypes())
{
//optional check to filter types (by interface or attribute, etc.)
//Add type to type map
}
}
Handling the AssemblyLoad event takes care of dynamically loaded assemblies.
From what I understand, Type.GUID uses the assembly version of the type as part of the Guid generation algorithm. This may lead to trouble if you increment your assembly version numbers. Using the GetDeterministicGuid method described in another answer would probably be advisable, depending on your application.
Don't loop to compare. Populate a Dictionary<Type>
and use the Contains
method.
Dictionary<Type> types = new Dictionary<Types>();
... //populate
if (types.Contains(someObject.GetType()))
//do something
This will certainly give you a fixed size entry, since all of them will be object references (instances of Type essentially being factory objects).
why not use the designated property for that, ie. AssemblyQualifiedName? This property is documented as "can be persisted and later used to load the Type".
The GUID is for COM interop.
What about (from Generating Deterministic GUIDs):
private Guid GetDeterministicGuid(string input)
{
// use MD5 hash to get a 16-byte hash of the string:
MD5CryptoServiceProvider provider = new MD5CryptoServiceProvider();
byte[] inputBytes = Encoding.Default.GetBytes(input);
byte[] hashBytes = provider.ComputeHash(inputBytes);
// generate a guid from the hash:
Guid hashGuid = new Guid(hashBytes);
return hashGuid;
}
And throw in that typeof().AssemblyQualifiedName
. You could to store this data inside a Dictionary<string, Guid>
collection (or, whatever, a <Guid, string>
).
This way you'll have always a same GUID
for a given type (warning: collision is possible).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With