c# - 对已加载到应用程序域中的文件使用反射,而不是(再次)加载每个文件

标签 c# reflection appdomain

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

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

在代码审查期间,针对这段代码提出了两个问题。首先,一旦找到匹配类型,我们就无法缩短循环;我们需要遍历每个文件并在找到多个匹配类型时抛出异常。这让我想到了真正的问题......

代码审阅者想知道是否有更好的方法来加载每个文件。出于性能原因,我们想知道是否可以循环遍历应用程序域中已加载的文件,而不是为每个文件调用 Assembly.LoadFile(file)。我们想,如果每个文件已经加载,为什么还要加载它呢?这是一个合理的担忧吗?以这种方式加载文件是否与将文件加载到应用程序域中的方式相同?遍历每个文件以免浪费处理时间的有效方法是什么?

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

Loads the contents of an assembly file on the specified path.

我不确定这是否等同于文件加载到应用程序域的方式,或者这是否完全不同。

最佳答案

如果您使用 LoadFrom 而不是 LoadFile,您不必担心 - 如果 DLL 已经加载,则不会再次加载 - 请参阅http://msdn.microsoft.com/en-us/library/1009fa28.aspx .但是,请注意,这是基于程序集身份而不是路径,因此如果您担心可能有两个程序集,每个程序集具有相同的身份但路径不同,那么您每次都必须显式加载它们。

如果您真的想深入了解这一点,您可以使用 AppDomain.CurrentDomain.GetAssemblies 获取应用程序域中加载的所有程序集,构建字典或类似结构并跳过那些已加载的程序集.但是,正如我所说,在典型情况下并使用 LoadFrom,这是不必要的。

关于c# - 对已加载到应用程序域中的文件使用反射,而不是(再次)加载每个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20476352/

相关文章:

c# - 为什么我不应该使用反射实现 Equals 和 GetHashCode?

c# - 无法将透明代理强制转换为来自 AppDomain 的类型

c# - 如何通过 UnhandledException 卸载 AppDomain

c# - 匿名类的通用列表

c# - 表单之间通信的最佳方式?

c# - 在零缩放的谷歌地图中,​​一个像素代表多少经度和纬度?

grails 反射 - 调用动态标签

java - 为什么 Class#getComponentType 返回 null 而不是 ArrayList (Java) 的泛型类型?

appdomain - 程序集无法在影子复制的 AppDomain 中加载

c# - 使用 .net 标准以编程方式创建服务总线订阅