对已经在应用程序域中加载的文件使用反射,而不是再次加载每个文件

Bob*_*orn 1 c# reflection appdomain

我正在使用反射来扫描文件夹中的所有程序集,以实现实现特定接口并从特定基类派生的类型。代码如下:

foreach (string file in Directory.GetFiles(folder, "*.dll"))
{
    Assembly assembly = Assembly.LoadFile(file);

    Type foundType = (from type in assembly.GetTypes()
                      where type.GetInterfaces().Contains(typeof(TInterface))
                   && type.BaseType.Name.LeftOf('`') == baseClass.Name.LeftOf('`')
                      select type).FirstOrDefault();

    if (foundType == default(Type)) { continue; }

    // Register our type so we don't need to use reflection on subsequent requests.
    DependencyContainer.Register(typeof(TInterface), foundType);

    return CreateInstance<TInterface>(foundType);
}
Run Code Online (Sandbox Code Playgroud)

在代码审查期间,针对这段代码提出了两个问题。首先,一旦找到匹配的类型,我们将无法缩短循环;如果发现多个匹配类型,则需要遍历每个文件并引发异常。那把我带到这里真正的问题...

代码审查者想知道是否有更好的方法来加载每个文件。出于性能原因,我们想知道是否可以遍历应用程序域中已加载的文件,而不是调用Assembly.LoadFile(file)每个文件。我们认为,为什么要加载每个已加载的文件?这是一个有效的问题吗?这种加载文件的方式与将文件加载到应用程序域中的方式相同吗?什么是遍历每个文件的有效方法,这样我们就不会浪费处理时间?

注意:Assembly.LoadFile()的文档不是很有帮助:

在指定路径上加载程序集文件的内容。

我不确定这是否等同于将文件加载到应用程序域中的方式,还是完全不同的情况。

Lua*_*aan 5

如果使用LoadFrom而不是LoadFile,则不必担心-如果DLL已经加载,则不会再次加载-请参阅http://msdn.microsoft.com/zh-cn/library/1009fa28.aspx。但是,请注意,这是基于程序集标识而不是路径,因此,如果您担心可能存在两个具有相同标识但路径不同的程序集,则每次都必须明确地加载它们。

如果您真的想对此进行更深入的研究,则可以使用AppDomain.CurrentDomain.GetAssemblies,构建字典或某种此类结构并跳过已经加载的程序集,将所有程序集加载到应用程序域中。但是,正如我所说,在典型情况下并使用LoadFrom,是没有必要的。