C#Assembly.Load与Assembly.ReflectionOnlyLoad

我想了解Assembly.Load和Assembly.ReflectionOnlyLoad之间的区别。

在下面的代码中,我试图从一个给定的接口inheritance给定的程序集中的所有对象:

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); } } 

这段代码对我来说工作正常,但是我正在对其他可能更好的替代方法进行一些研究,并且遇到了Assembly.ReflectionOnlyLoad()方法。

我认为,因为我没有加载或执行任何对象,基本上只是查询他们的定义,我可以使用ReflectionOnlyLoad稍微提高性能…

但事实certificate,当我将Assembly.Load更改为Assembly.ReflectionOnlyLoad时,它调用assembly.GetTypes()时出现以下错误:

 System.Reflection.ReflectionTypeLoadException: 

无法加载一个或多个请求的types。 检索LoaderExceptions属性以获取更多信息。

我认为上面的代码只是做reflection和“看”图书馆……但是这是海森堡不确定性原理的某种实例,看图书馆和其中的对象实际上是试图实例化它们在一些办法?

谢谢,马克斯

根据Jon的回答,了解LoaderExceptions内容将会很有帮助。 代替这些信息,我认为我可以冒险猜测。 来自MSDN :

如果程序集有依赖关系,ReflectionOnlyLoad方法不加载它们。 如果你需要检查它们,你必须自己加载它们。

您需要将一个处理程序附加到AppDomain.ReflectionOnlyAssemblyResolve以帮助CLR加载您正在加载的程序集的任何依赖关系。 你做到了吗?

我相信你对Load和ReflectionOnlyLoad之间区别的一般理解是正确的。 这个问题(我认为)是,即使简单地加载一个types,CLR也需要从定义types本身的程序集中读取元数据,并从定义types祖先的每个程序集中加载元数据 。 因此,您需要在所有定义types的Assembly上调用Assembly.ReflectionOnlyLoad,这些types是要加载的types的祖先。

举个例子,假设你在程序集A.dll中定义了以下类。

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

以及程序集B.dll中定义的以下类。

 public class MySubclass : MyBase { } 

在程序集B.dll上调用Assembly.GetTypes时,CLR将尝试加载typesMySubclass及其所有成员。 由于方法Foo是在程序集A.dll中的MyBase中定义的(并且在B.dll的元数据中无处存在),所以如果程序集A.dll尚未加载,CLR将抛出types加载exception。

ReflectionOnly方法是您可以在磁盘上加载特定程序集的唯一方法,无需经过通常的Load / LoadFrom规则即可进行检查。 例如,您可以使用与GAC中相同的标识加载一个基于磁盘的程序集。 如果您使用LoadFrom或LoadFile尝试了此操作,则GAC程序集始终处于加载状态。

此外,您可能不会在返回的Assembly实例上调用GetCustomAttributes(…),因为这将尝试实例化Assembly上的属性ReflectionOnly。 您必须使用CustomAttributeData类的静态方法。

通过ReflectionOnly加载的程序集中的任何types都可以被实例化。

没有方法可以从程序集执行,用ReflectionOnlyLoad()加载,你会得到InvalidOperationException 。 所以这是使用reflection来确定assembly内容的安全方法。

Interesting Posts