Getting a TypeDefintion for mscorlib Type

Apr 21, 2009 at 4:59 PM
Long story short: How do I get a TypeDefintion for ArgumentNullException?

I've looked all over in the API, and while I've stumbled across PlatformType, AssemblyReference collections, etc., I can't seem to figure out how I can do this. This seems like this should be something very easy so I'm guessing I'm missing the obvious :).

Basically the real problem is: how can I traverse types within mscorlib?

Any help would be appreciated.
Apr 21, 2009 at 9:17 PM
Never mind, I figured it out. It may not be the right way...but it works.

First, I got mscorlib loaded (note, SR == System.Reflection)

this.mscorlib = this.host.LoadAssembly(new AssemblyIdentity(
    this.host.CoreAssemblySymbolicIdentity, SR.Assembly.GetAssembly(typeof(object)).Location));

then it was fairly easy to get the type:

from type in this.mscorlib.GetAllTypes()
    where type.ToString() == typeof(ArgumentNullException).ToString()

Apr 23, 2009 at 9:50 PM
You may not want to use System.Reflection API for such purposes.
If you need to create a reference to a platform type, you can employ CreateReference() from PlatformType class (just subclass PlatformType and add a property you need).

Now there is an example in Metadata samples folder that finds in an assembly every method throwing System.ArgumentNullException, using exactly this approach.

Apr 24, 2009 at 1:07 PM
Matko,

I'm only using System.Reflection to find where mscorlib.dll is located on disk. That's it. Plus I need to find more than just one type from that assembly - once it's loaded it's easy to use LINQ to find what I need.

Ah, that example you mentioned must've been added recently, I just did a "get latest" and there it is. I'll take a look at it.

Regards,
Jason
Coordinator
Apr 24, 2009 at 3:09 PM
Doing typeof(object).Location to get the location of mscorlib is OK, but since the base class for the host already does that, there is no need to do it again.

The CCI object model does not prescribe the behavior of the ToString method on type objects. Perhaps it should, but right now it does not, so its best not to depend on it. Also, ToString, in the cases where the reader implements it "properly", returns the result of TypeHelper.GetTypeName, which returns a C# like string, which is not always the same as the string returned by System.Type.ToString().

In your example, I'd rather write UnitHelper.FindType(host.NameTable, this.mscorlib, "System.ArgumentNullException"), which is going to a far more efficient search of all of the types than LINQ will.

And, of course, types that you know you are going to look for (i.e. their names are not derived from user input) may as well become properties of your own subtype of PlatformTypes, as Matko's example illustrates. The other nice thing about PlatformTypes is that it does not require you to find and load mscorlib. Also, since the properties are lazy, the identity of mscorlib can be discovered from the assembly you want to analyze, provided that you load that first, so your tool will automatically become independent of the version of the CLR that you are running on.
Apr 24, 2009 at 3:47 PM
OK, I'm starting to see the benefit of CreateReference() on PlatformType - I think I'll restructure my code to go with this approach instead.

Regards,
Jason
Apr 24, 2009 at 5:33 PM
One small issue ... CreateReference() returns a INamespaceTypeReference, and what I need to find is a method within the create types. But if I use ResolvedType, the Methods enumerable is empty. Using TypeHelper doesn't help either:

            var aType = this.mscorlib.GetType("System", "ArgumentNullException");
            var method = TypeHelper.GetMethod(aType.ResolvedType,
                new Name() { Value = ".ctor" }, this.host.PlatformType.SystemString);

In this code, aType is correct, but method is a "dummy" method. Note that Name is just a simple custom implementation of IName.

I'm probably missing something really obvious here ...
Coordinator
Apr 24, 2009 at 6:30 PM
Check if aType.ResolvedType actually results in the type you expect. The reference will not resolve unless you actually load the assembly that it references.
Apr 24, 2009 at 6:58 PM
aType.ResolvedType gives a "dummy" type. But aType is {System.ArgumentNullException}, and System.ArgumentNullException is a mscorlib type. In a previous post, I thought you said that I could use PlatformType to find mscorlib-based types easier than the other approach I was using. So how would I ensure that mscorlib is "loaded"?
Apr 24, 2009 at 7:03 PM
Actually, the same thing happens in the FindThrowPlatformType sample project. In Program.cs at line 73, this.systemArgumentNullException is set, but its' ResolvedType value is a "dummy" value.
Apr 24, 2009 at 8:40 PM
OK, I had to reread one of your posts before I understood that I still had to load mscorlib. But what I don't get is that you say "Doing typeof(object).Location to get the location of mscorlib is OK, but since the base class for the host already does that, there is no need to do it again." Are you saying the host automatically loads mscorlib? Or that there's a Location-like property somewhere on the host that I can use to load mscorlib?

Once I put my mscorlib LoadUnitFrom() code back in, I was able to have aType.ResolvedType "work", but TypeHelper.GetMethod() still fails. Still digging...
Apr 24, 2009 at 8:54 PM
Oh, wait. Looking at the implementation of GetMethod, it's looking to match the UniqueKey (which in this case is 41194). But how would I know that value off the cuff? I mean, I know the method name is ".ctor" but that key...how is that even generated? It seems like it's always 41194 but that could just be coincidence.
Coordinator
Apr 25, 2009 at 1:36 AM
The host base class does not load any assemblies by default, so you still have to do that. The base class implementation of IMetadataHost.CoreAssemblyIdentity constructs an assembly identity in the same way as your sample code, in the case where none of the loaded assemblies has an opinion on the identity of mscorlib. The base class can do a lot more to help with probing for assemblies in likely places, but this is work that remains to be done.

The value of UniqueKey is decided by the nametable object. Your implementation of IName will have to call INameTable.GetNameFor(Value) in order to get the value to return for IName.UniqueKey. It is not usual to have your own implementation for IName, since you can get IName objects from INameTable.
Apr 27, 2009 at 2:38 PM
Herman,

Ah! OK, now I get INameTable - I was over-analyzing it. It's far easier than what I thought it would take to use correctly. Now TypeHelper.GetMethod() is working perfectly - thanks!

Regards,
Jason