Wednesday 19 March 2008

Reflection - using GetType(string) to create an instance of a type is returning null

My colleague "CS" today had issues with resolving types in our Lookup Service. The problem: he was trying to use GetType(string) to resolve a type that was in another assembly. e.g. Type sourceType = GetType(string.Format("DDK.Common.Lookups{0}",lookupTypeName))

Problem was that it couldn't resolve the name - even though the dll was referenced and the calling assembly could resolve the name if it needed to.

This article is much better than MSDN in explaning the issue http://blogs.msdn.com/haibo_luo/archive/2005/08/21/454213.aspx. In attempting to resolve the type, GetType() will first look in the current calling assembly, then in mscorlib. It will NOT trawl through all your references in the bin directory for you like it does with normal type resolution - it will just give up if it is not in mscorlib or the current assembly and return a whopping great null.

Instead, you have to give the .NET runtime a hand and tell it which assembly to look in. This is why you have to do the same thing when specifying dynamically loaded types in the web.config - you have to put the fully qualified names so the runtime it can resolve the type with the same GetType(string) mechanism. The simplest way to find this out is to just look at the project properties to find the name of the output assembly name. Alternatively, you can make an instance of your object e.g. new DDK.Common.Lookups.Country().GetType().AssemblyQualifiedName to get the full name that the runtime uses to uniquely identify the type.

In our case, changing the code to include the red (ie the AssemblyQualifiedName minus any version numbers did the trick). ie
Type sourceType = GetType(string.Format("DDK.Common.Lookups.{0}, DDK.Common.Lookups",lookupTypeName))


2 comments:

Chook said...

Thanks, David! This was helpful.

Gabriel B. said...

This is one of the shittiest thing ever, since in its basic form it's so simple.

Here's what I've done using System.Reflection ;)

thisassembly = some_temp_object.GetType().Assembly.FullName.
Substring(0,some_temp_object.GetType().
Assembly.FullName.IndexOf(','));

THIS gets the correct assembly name

Type MyType = Type.GetType("The namespace of the f-ing class." + className + "," + thisassembly, true);

So yeah, the syntax of the string argument of getType() is "Namespace.Location.ClassName, AssemblyName" which is pretty straightforward if you have it written in this way.

This comment WILL help millions!