21

In numerous places do I encounter partially qualified type names of the form FullTypeName, AssemblyName, i.e. like Type.AssemblyQualifiedName only without the version, culture and publicKeyToken qualifiers.

My question is how can one convert it to the respective Type in a minimum of effort? I thought that Type.GetType does the job, but alas, it does not. The following code, for instance, returns null:

Type.GetType("System.Net.Sockets.SocketException, System");

Of course, if I specify the fully qualified name it does work:

Type.GetType("System.Net.Sockets.SocketException, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");

Thanks a lot.

mark
  • 59,016
  • 79
  • 296
  • 580
  • Do you have the type at compile time? If so why not use typeof().FullName, et. al? If you have the type at runtime you can use .GetType().FullName et. al. Or am I missing the specific request? I get that you only want to specify a partial name, but thats really more for the loader than it is for the type system. FQNs are for disambiguating reference issues for the rare occassions where name conflicts occur, which is truthfully more often in user assemblies than in BCL assemblies. – GrayWizardx Mar 02 '10 at 23:36
  • 1
    I am perfectly aware of typeof() or Type.FullName. The type of the object is read from a configuration file, that is why I use Type.GetType. And this is why I am so interested in understanding how partially qualified type names work. – mark Mar 03 '10 at 07:17

5 Answers5

32

If the assembly has been loaded in the current domain then the code below usually works:

public static Type GetTypeEx(string fullTypeName)
{
    return Type.GetType(fullTypeName) ??
           AppDomain.CurrentDomain.GetAssemblies()
                    .Select(a => a.GetType(fullTypeName))
                    .FirstOrDefault(t => t != null);
}

You can use it like so:

Type t = GetTypeEx("System.Net.Sockets.SocketException");
Nathan Baulch
  • 20,233
  • 5
  • 52
  • 56
dmihailescu
  • 329
  • 4
  • 4
9

If the DLL it's in isn't already loaded into the application domain (e.g. you used it), you need the full path like this, if it's already loaded, it can find it with the shorter version.

To answer your question: the second version always works, stick with it and you have one way to worry about.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • 1
    I don't think it matters whether or not the assembly is already loaded - the short version won't work. The namespace-qualified name will work if the type is either in the currently executing assembly or in mscorlib. Fuller explanation below. – lesscode Jan 06 '15 at 14:03
3

True, Type.GetType(string) does require an AssemblyQualifiedName. This can be in many forms:

MyNS.MyType, MyAssembly, Version=x.x.x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX

The following are also valid AssemblyQualifiedNames:

MyNS.MyType, MyAssembly, Version=x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly, Culture=xxx, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX
MyNS.MyType, MyAssembly

For a signed assembly, the minimum required for a FullyQualifiedAssemblyName is:

MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX

For an unsigned assembly, the minimum required for a FullyQualifiedAssemblyName is:

MyNS.MyType, MyAssembly

No need for all the "hand waving" going on in the code snippets others have provided. Ensure that your type names are set up properly and you can access your types (and load assemblies dynamically) with a high degree of flexibility. I do this regularly.

In OP's example using:

Type.GetType("System.Net.Sockets.SocketException, System")

The reason for the failure was the absence of the PublicKeyToken. The .Net FW assemblies are all signed and therefore require the PublicKeyToken to resolve the Assembly name. The following would work:

Type.GetType("System.Net.Sockets.SocketException, System, PublicKeyToken=b77a5c561934e089")
Capt Nasty
  • 89
  • 2
  • Frankly this should be the way MSDN explains it. Makes a lot of sense, and explains why this method behaves so seemingly inconsistently in a lot of scenarios. – tobriand Nov 06 '19 at 11:52
2

Code working with the short form is:

    Assembly a = Assembly.LoadWithPartialName(assemblyName);
    Type t = a.GetType(typeName);

but LoadWithPartialName is deprecated, so I guess you should stick with the long form.

Timores
  • 14,439
  • 3
  • 46
  • 46
2

Having just gone through a similar issue with some legacy code, I don't think that the first statement in the accepted answer is correct. It doesn't matter whether or not the assembly is already loaded.

According to the documentation, Type.GetType(string) requires an AssemblyQualifiedName, unless the type in question is in the currently executing assembly or in mscorlib, in which case the namespace-qualified type name is all that is required.

Note that an AssemblyQualifiedName includes the full DisplayName of the type's assembly (with version, culture and public key token).

The short version won't work unless you intercept the failed type load with a custom AssemblyResolver (which was actually the case with my issue, masking another problem).

lesscode
  • 6,221
  • 30
  • 58