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内容的安全方法。