.Net Framework 2.0 introduces several new assembly loading APIs.
Assembly.ReflectionOnlyLoadFrom(String assemblyFile)
Assembly.ReflectionOnlyLoad(byte[] rawAssembly)
Assembly.ReflectionOnlyLoad(String assemblyName)
And Assembly class now has ReflectionOnly property to tell you if an assembly is loaded as reflection only or not.
As you can infer from the name of those APIs, Assembly returned from those APIs can only be used for reflection. Any intention to create an instance of types in those assemblies will result in InvalidOperationException.
There are a few scenarios those APIs address:
The normal assembly loading APIs can’t satisfy those scenarios, for the following reasons:
For those reasons, Reflection Only Assembly Load APIs will:
Reflection Only Assembly Load APIs behave quite differently from the execution assembly load APIs.
<Update date="2005/09/18">
In .Net framework 2.0 ReflectionOnly APIs cannot be used to reflect other mscorlib.dll (for example, v1.0/v1.1/NetCF). The reason is that mscorlib.dll is being special cased by CLR Loader all over the code base. It will be a major work to make it work. This may be possible in future version of .Net framework.
</Update>
So how will you use the Reflection Only Assembly Load APIs?
I recommend using Assembly.ReflectionOnlyLoadFrom whenever possible, and only use Assembly.ReflectionOnlyLoad for assemblies in GAC. The reason is the same as CLR not probing dependencies --- when CLR starts probing application base, it may return something you don’t want.
Here is a very simple sample application showing using Reflection Only Assembly Load APIs.
C:\ >more test.cs
using System;
using System.IO;
using System.Reflection;
public class ReflectionOnlyLoadTest
{
public ReflectionOnlyLoadTest(String rootAssembly)
m_rootAssembly = rootAssembly;
}
public static void Main(String[] args)
if (args.Length != 1) {
Console.WriteLine("Usage: Test assemblyPath");
return;
try {
ReflectionOnlyLoadTest rolt = new ReflectionOnlyLoadTest(args[0]);
rolt.Run();
catch (Exception e) {
Console.WriteLine("Exception: {0}!!!", e.Message);
internal void Run()
AppDomain curDomain = AppDomain.CurrentDomain;
curDomain.ReflectionOnlyPreBindAssemblyResolve += new ResolveEventHandler(MyReflectionOnlyResolveEventHandler);
Assembly asm = Assembly.ReflectionOnlyLoadFrom(m_rootAssembly);
// force loading all the dependencies
Type[] types = asm.GetTypes();
// show reflection only assemblies in current appdomain
Console.WriteLine("------------- Inspection Context --------------");
foreach (Assembly a in curDomain.ReflectionOnlyGetAssemblies())
Console.WriteLine("Assembly Location: {0}", a.Location);
Console.WriteLine("Assembly Name: {0}", a.FullName);
Console.WriteLine();
private Assembly MyReflectionOnlyResolveEventHandler(object sender, ResolveEventArgs args)
AssemblyName name = new AssemblyName(args.Name);
String asmToCheck = Path.GetDirectoryName(m_rootAssembly) + "\\" + name.Name + ".dll";
if (File.Exists(asmToCheck)) {
return Assembly.ReflectionOnlyLoadFrom(asmToCheck);
return Assembly.ReflectionOnlyLoad(args.Name);
private String m_rootAssembly;
C:\ >test c:\windows\Microsoft.NET\Framework\v2.0.40607\system.dll
------------- Inspection Context --------------
Assembly Location: c:\windows\Microsoft.NET\Framework\v2.0.40607\system.dll
Assembly Name: System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5
c561934e089
Assembly Location: c:\windows\Microsoft.NET\Framework\v2.0.40607\Microsoft.Vsa.d
ll
Assembly Name: Microsoft.Vsa, Version=8.0.1200.0, Culture=neutral, PublicKeyToke
n=b03f5f7f11d50a3a
Assembly Location: c:\windows\Microsoft.NET\Framework\v2.0.40607\System.Xml.dll
Assembly Name: System.Xml, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b
77a5c561934e089