如何从另一个文件夹中加载的程序集中获取类型?

Cui*_*崔鹏飞 7 .net c# reflection

我使用以下代码:

Assembly.LoadFile("the assembly in another folder");
var type = Type.GetType("the full name of the type");
Run Code Online (Sandbox Code Playgroud)

尽管在这行代码之前已经加载了程序集,但它总是返回null type.

PS:我确实传递了程序集限定名,包括名称空间,类型名称,程序集名称,版本和公共令牌.

Ste*_*ham 9

Type.GetType除非您传递类型的程序集限定名称,否则只搜索调用程序集中的类型和mscorlib.dll中的类型.看这里.

编辑

它似乎Type.GetType只能Type从Load上下文中的程序集中检索实例.使用加载的程序集LoadFile是在没有上下文和那些使用加载LoadFrom是在Load从上下文; 这些上下文都不允许您使用,Type.GetType因此分辨率将失败.本文显示,当它所在的目录被添加为探测私有路径时,Type可以检索信息,Assembly因为它将最终在Load上下文中,但在其他上下文中将失败.


Abe*_*bel 5

当您必须Type.GetType(string)在不在加载上下文中但在加载上下文或无上下文上下文中的程序集中使用类型时,执行此操作的“正确”(MS 推荐)方法是绑定到Appdomain.AssemblyResolve事件。下面的代码比较高效:

// this resolver works as long as the assembly is already loaded
// with LoadFile/LoadFrom or Load(string) / Load(byte[])
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
    var asm = (from a in AppDomain.CurrentDomain.GetAssemblies()
              where a.GetName().FullName == args.Name
              select a).FirstOrDefault();

    if(asm == null)
         throw FileNotFoundException(args.Name);     // this becomes inner exc

    return asm;
}

// place this somewhere in the beginning of your app:
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
Run Code Online (Sandbox Code Playgroud)

创建 AssemblyLoad/Resolve 事件的组合以保留已加载程序集的字典(使用程序集名称作为键)似乎更有效。

在 Assembly.LoadFile
上使用这种方法有一些严重的缺点。根据 MSDN

LoadFile 不会将文件加载到 LoadFrom 上下文中,并且不会像 LoadFrom 方法那样使用加载路径解析依赖项。

因此,如果可能,请不要使用 LoadFile。生成的程序集在无上下文上下文中加载,这比从上下文加载的缺点更多。相反,使用Assembly.LoadFrom并且依赖项将自动从加载路径加载。