C # Assembly.Load vs. Assembly.ReflectionOnlyLoad

I am trying to understand the differences between Assembly.Load and Assembly.ReflectionOnlyLoad.

In the code below, I try to find all the objects in this assembly that inherit from this interface:

var myTypes = new List<Type>(); var assembly = Assembly.Load("MyProject.Components"); foreach (var type in assembly.GetTypes()) { if (type.GetInterfaces().Contains(typeof(ISuperInterface))) { myTypes.Add(type); } } 

This code works fine for me, but I explored other, perhaps better alternatives, and came across the Assembly.ReflectionOnlyLoad () method.

I assumed that since I am not loading or running any objects, essentially just asking for their definitions, I could use ReflectionOnlyLoad to slightly improve performance ...

But it turns out that when I change Assembly.Load to Assembly.ReflectionOnlyLoad, I get the following error when it calls assembly.GetTypes ():

 System.Reflection.ReflectionTypeLoadException: 

Unable to load one or more of the requested types. Check out the LoaderExceptions property for more info.

I assumed that the above JUST code reflects and “looks at” the library ... but is this some kind of Heisenberg uncertainty principle in which viewing the library and objects in it actually tries to create an instance in some way?

Thanks Max

+42
reflection c #
Nov 20 '08 at 16:08
source share
4 answers

According to John, it would be helpful to know what is in LoaderExceptions . Instead of this information, I think I can take a chance. From MSDN :

If the assembly has dependencies, ReflectionOnlyLoad Method do not load them. If you need to study them, you must download them yourself.

You need to attach a handler to AppDomain.ReflectionOnlyAssemblyResolve to help the CLR load any dependencies of the loadable assembly. Did you do it?

+23
Nov 20 '08 at 17:14
source share

I believe your general understanding of the differences between Load and ReflectionOnlyLoad is correct. The problem here (I think) is that even for a simple CLR type load, you need to read metadata from the assembly, the type itself is determined, and it also loads metadata from each assembly in which the ancestor types are specified. So, you need to call Assembly.ReflectionOnlyLoad for all assemblies that define types that are the ancestors of the types you load.

To give an example, suppose you have the following class defined in assembly A.dll.

 public class MyBase { public void Foo() { } } 

and the next class defined in assembly B.dll.

 public class MySubclass : MyBase { } 

When you call Assembly.GetTypes on assembly B.dll, the CLR will try to load the MySubclass type and all its members. Since the Foo method is defined in MyBase in the A.dll assembly (and does not exist anywhere in the B.dll metadata), the CLR will throw type load exceptions if the A.dll assembly has not been loaded.

+8
Nov 20 '08 at 18:12
source share

Methods ReflectionOnly is the only way to load a specific assembly onto disk to verify without following the usual Load / LoadFrom rules. For example, you can load a disk-based assembly with the same identifier as in the GAC. If you tried this with LoadFrom or LoadFile, the GAC assembly will ALWAYS be loaded.

Also, you cannot call GetCustomAttributes (...) on an instance of Assembly Assembly, as this will try to instantiate the assembly attributes, which are ReflectionOnly. To do this, you must use the static methods of the CustomAttributeData class.

No types in the assembly loaded through ReflectionOnly can be created.

+6
Nov 20 '08 at 20:02
source share

No method can be executed from the assembly loaded using ReflectionOnlyLoad() , you will get an InvalidOperationException . Thus, this is a safe way to determine the contents of an assembly using reflection.

+1
Mar 19 '09 at 13:44
source share



All Articles