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

C# 对应用程序域中已加载的文件使用反射,而不是(再次)加载每个文件,c#,reflection,appdomain,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.Get

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

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);
}
foreach(目录.GetFiles(文件夹“*.dll”)中的字符串文件)
{
Assembly=Assembly.LoadFile(文件);
类型foundType=(来自assembly.GetTypes()中的类型)
其中type.GetInterfaces()包含(typeof(TInterface))
&&type.BaseType.Name.LeftOf('`')==baseClass.Name.LeftOf('`'))
选择类型).FirstOrDefault();
如果(foundType==default(Type)){continue;}
//注册我们的类型,这样我们就不需要在后续请求中使用反射。
DependencyContainer.Register(typeof(TInterface),foundType);
返回CreateInstance(foundType);
}
在代码审查期间,提出了关于这段代码的两个问题。首先,一旦找到匹配的类型,我们就不能缩短循环;我们需要遍历每个文件,如果找到多个匹配类型,则抛出异常。这让我想到了真正的问题

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

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

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


我不确定这是否等同于如何将文件加载到应用程序域,或者这是一种完全不同的情况。

如果使用
LoadFrom
而不是
LoadFile
,您不必担心这一点-如果DLL已经加载,它将不会再次加载-请参阅。但是,请注意,这是基于程序集标识,而不是路径,因此如果您担心可能有两个程序集,每个程序集具有相同的标识但具有不同的路径,那么每次都必须显式加载它们


如果您确实想更深入地了解这一点,可以使用
AppDomain.CurrentDomain.GetAssemblies
在应用程序域中加载所有程序集,构建字典或某些类似结构,并跳过已加载的程序集。但是,正如我所说,在一个典型的场景中,使用
LoadFrom
,这是不必要的。

如果您使用
LoadFrom
而不是
LoadFile
,您不必担心这一点-如果DLL已经加载,它将不会再次加载-请参阅。但是,请注意,这是基于程序集标识,而不是路径,因此如果您担心可能有两个程序集,每个程序集具有相同的标识但具有不同的路径,那么每次都必须显式加载它们


如果您确实想更深入地了解这一点,可以使用
AppDomain.CurrentDomain.GetAssemblies
在应用程序域中加载所有程序集,构建字典或某些类似结构,并跳过已加载的程序集。但是,正如我所说的,在一个典型的场景中,使用
LoadFrom
,这是不必要的。

我不知道
Assembly.LoadFile(file)
是如何工作的。但是您可以通过
AppDomain.CurrentDomain.GetAssemblies()

根据已加载的程序集检查每个程序集。我不知道
assembly.LoadFile(file)
的具体行为。但是,您始终可以通过
AppDomain.CurrentDomain.getAssemblys()

将文件夹添加到私有探测路径,然后使用
assembly.Load(string)
在加载上下文中加载程序集,从而对照已加载的程序集检查每个单独的程序集。据我所知,这是推荐的方法。有关程序集加载的更多信息和建议,请查看的MSDN博客。

另一种方法是将文件夹添加到专用探测路径,然后使用在加载上下文中加载程序集的
assembly.Load(string)
。据我所知,这是推荐的方法。查看的MSDN博客以获取有关程序集加载的更多信息和建议。

为什么不使用
AppDomain.CurrentDomain.GetAssemblies()
?@haim770我有一个注意事项要做,但我不知道这是否与
LoadFile()
相同,我不知道调用时是否加载了所有程序集。如果我知道这一点,我可能会做好一切。@Mathew我可以,也许应该。那是另一个问题。谢谢你的提示。对落选者说:为什么要落选?了解原因会有帮助。为什么不使用
AppDomain.CurrentDomain.GetAssemblies()
?@haim770我有一个说明要准确地做到这一点,但我不知道这是否与
LoadFile()
相同,我也不知道调用时是否加载了所有程序集。如果我知道这一点,我可能会做好一切。@Mathew我可以,也许应该。那是另一个问题。谢谢你的提示。对落选者说:为什么要落选?知道为什么会有帮助。