【问题标题】:Reflection vs. Attributes in plugin architecture插件架构中的反射与属性
【发布时间】:2023-03-10 09:25:01
【问题描述】:

我正在开发一个在启动时从子目录加载插件的应用程序,目前我正在通过使用反射来迭代每个程序集的类型并找到实现 IPluginModule 接口的公共类来做到这一点。

由于反射涉及性能损失,并且我预计一段时间后会有多个插件,我想知道定义在程序集级别应用的自定义属性是否有用,可以在迭代类型之前检查该属性(在一个程序集中可能有十几种类型,包括 IPluginModule 的 1 个实现者)。

该属性(如果存在)然后可以提供一种方法来返回所需的类型或实例,并且迭代这些类型将只是一种回退机制。不能将类型信息存储在配置文件中。

这会提高性能,还是与实际从存储中加载程序集所需的时间相比无关紧要?另外,这种用法是否适合属性?

【问题讨论】:

  • 性能受到影响?我希望来自 Java,而不是来自 C# - 我很想知道您是否以及如何衡量它。

标签: c# .net reflection architecture plugins


【解决方案1】:

我会用一个问题来回答你的问题:你为什么担心这个?

您担心一次性操作会影响潜在的性能,因为以后可能会有多个插件。

除非您的应用程序启动时间对用户来说过长,否则我不会浪费时间去考虑它 - 您可能可以做一些更好的事情来改进您的应用程序。

【讨论】:

  • 我首先尝试了配置建议,但后来我发现它几乎没有区别,因为无论如何我都必须使用 Activator/Assembly.CreateInstance。现在我正在使用自定义程序集级属性来获取类型名称,正如您猜到的那样,我已经找到了可以改善启动时间的其他领域。
  • 是的,配置你只会错过循环并检查一个类是否实现了你的接口......你只会知道哪些实现了。
  • 加载和获取所有类型的许多程序集的列表可能是性能和内存问题。通过获取所有类型,您在内存中加载了 CLR 通常会延迟加载的大量类型基础结构。这是需要考虑的事情。
【解决方案2】:

您还可以在配置中包含可插入类型,这样您就可以知道确切的类,而不是遍历所有类。必须为此选项提供一些配置实用程序...但可能会根据您循环通过的类的数量获得很好的性能提升。

【讨论】:

  • +1 -- 这正是我的做法。在配置中向应用程序注册插件。然后我使用自定义部分处理程序来实际加载插件。
  • 我也只在第一次添加程序集时对其进行迭代。我提取了以后需要的详细信息(加上一些用户友好的信息)。此数据被序列化以供以后使用(通过 Activator)。用户还可以在启动时选择“自动实例化”插件。
【解决方案3】:

我相信 Microsoft 的两个 .net 插件框架,托管插件框架 (MAF) 和托管可扩展性框架 (MEF) 都可以使用属性或反射来发现插件。所以微软似乎觉得属性是合适的。

不过,我不确定性能差异是什么。

【讨论】:

    【解决方案4】:

    一个好的解决方案是缓存插件的所有信息。第一次启动应用程序时,它会全面扫描插件 dll,并保存在文件中找到的类型列表。下次应用程序启动时,它会从文件中加载信息,这将比再次扫描所有 dll 快得多。该应用程序还可以存储每个 dll 的时间戳,因此如果它检测到 dll 中的更改,它可以重新扫描它并更新缓存。

    这基本上就是Mono.Addins framework所遵循的方法。

    【讨论】:

      【解决方案5】:

      我原以为向程序集询问所有带有属性标记的类也会使用反射。然后归结为在元数据、接口实现或属性标记中查找哪个更快?

      【讨论】:

      • 我想我在某处读到过元数据的查看速度更快。但实际上我们只是在谈论毫秒,我敢肯定。
      猜你喜欢
      • 2011-06-08
      • 2015-04-12
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-17
      • 2012-01-30
      • 1970-01-01
      相关资源
      最近更新 更多