Type.GetType("typeName, assemblyName, version, culture") is a common way to load a type object. Unfortunately, the version of the assembly is frequently newer than the one given by the string. Your code might have saved the type name using the
Type.AssemblyQualifiedName property, which includes all assembly information, and later tried to load that type, even though the version might have changed. This article will demonstrate an easy way to load a type while ignoring the specific assembly version.
During the normal
Type.GetType() call, the
AppDomain object will raise an
AssemblyResolve event for any assembly it cannot find. (The type string may contain more than one subtype -- Generics.) An optional event handler may load and return an alternative assembly, or
null if no assembly is available.
OnAssemblyResolve handler receives the unresolved assembly name, uses the
AssemblyName object to parse it, and attempts to load an assembly with just the name, without any other information.
AssemblyResolve is global for the domain, so we must make sure that other threads, that might potentially try to resolve a type at the same time, do not unintentionally use the same functionality. A boolean field
_isGetTypeRunningOnThisThread marked with the
[ThreadStatic] attribute cleanly solves this problem.
public static Type GetTypeFromAnyAssemblyVersion(string typeName)
ResolveEventHandler assemblyResolve = OnAssemblyResolve;
AppDomain.CurrentDomain.AssemblyResolve += assemblyResolve;
_isGetTypeRunningOnThisThread = true;
_isGetTypeRunningOnThisThread = false;
AppDomain.CurrentDomain.AssemblyResolve -= assemblyResolve;
[ThreadStatic] private static bool _isGetTypeRunningOnThisThread;
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
Assembly assembly = null;
var an = new AssemblyName(args.Name);
if (an.Name != args.Name)
assembly = ((AppDomain) sender).Load(an.Name);