Max*_*ing 48 c# reflection assembly.load assembly.reflectiononly
我试图理解Assembly.Load和Assembly.ReflectionOnlyLoad之间的区别.
在下面的代码中,我试图找到从给定接口继承的给定程序集中的所有对象:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码对我来说很好,但我正在研究其他可能更好的替代方案,并遇到了Assembly.ReflectionOnlyLoad()方法.
我假设因为我没有加载或执行任何对象,基本上只是查询他们的定义我可以使用ReflectionOnlyLoad来略微提升性能......
但事实证明,当我将Assembly.Load更改为Assembly.ReflectionOnlyLoad时,我调用assembly.GetTypes()时会收到以下错误:
Run Code Online (Sandbox Code Playgroud)System.Reflection.ReflectionTypeLoadException:无法加载一个或多个请求的类型.检索LoaderExceptions属性以获取更多信息.
我假设上面的代码只是做反射和"查看"库...但是这是Heisenberg不确定性原理的某种实例,通过查看库和它中的对象实际上是试图在某些实例化它们办法?
谢谢,马克斯
C. *_* 76 10
我相信您对Load和ReflectionOnlyLoad之间差异的一般理解是正确的.这里的问题(我认为)即使只是简单地加载一个类型,CLR也需要从组件中读取元数据,类型本身也被定义,并且从定义类型祖先的每个程序集中加载元数据.因此,您需要在所有程序集上调用Assembly.ReflectionOnlyLoad,这些程序集定义作为您正在加载的类型的祖先的类型.
举个例子,假设您在程序集A.dll中定义了以下类.
public class MyBase
{
public void Foo() { }
}
Run Code Online (Sandbox Code Playgroud)
以及在程序集B.dll中定义的以下类.
public class MySubclass : MyBase
{
}
Run Code Online (Sandbox Code Playgroud)
当您在程序集B.dll上调用Assembly.GetTypes时,CLR将尝试加载MySubclass类型及其所有成员.因为方法Foo在程序集A.dll中的MyBase中定义(并且在B.dll的元数据中无处存在),所以如果尚未加载程序集A.dll,CLR将抛出类型加载异常.
ReflectionOnly方法是您可以在磁盘上加载特定程序集以进行检查的唯一方法,而无需通过通常的Load/LoadFrom规则.例如,您可以加载基于磁盘的程序集,其标识与GAC中的标识具有相同的标识.如果您使用LoadFrom或LoadFile尝试此操作,则始终加载GAC程序集.
此外,您可能不会在返回程序集实例上调用GetCustomAttributes(...),因为这将尝试实例化程序集上的属性,即ReflectionOnly.您必须使用CustomAttributeData类的静态方法.
通过ReflectionOnly加载的程序集中的任何类型都不会被实例化.