插件使用自己的 app.config

Posted

技术标签:

【中文标题】插件使用自己的 app.config【英文标题】:Plugin to use its own app.config 【发布时间】:2010-10-24 17:58:44 【问题描述】:

在一些人的帮助下,我终于设法构建了一个插件架构的工作解决方案,但现在出现了一个新问题。

我的托管应用程序使用它的 app.config 文件作为正在执行的程序集(这是一个 Windows 服务)的一些默认值。

每个插件都应该能够从单独的插件设置文件加载它自己的设置,因为主机不应该知道插件设置。在插件项目中,我还添加了一个 app.config 文件(带有一些设置和一个连接字符串),以便我可以实例化 Properties.Settings 类并在插件代码中使用它的属性。

问题是当我更改插件的 app.config 中的设置(构建为 plugin.dll.config)时,我看不到插件本身的这些更改,它仍然使用设计时设置。

有没有办法在每个插件中加载 app.config 设置,以便生成的 Properties.Settings 类可以工作?如果没有,是否有另一种方法可以将基于 app.config 的设置文件加载到插件中?我打算在 IPlugin 接口中添加一个 LoadConfiguration 方法,这样每个插件都会加载它自己的设置。

【问题讨论】:

【参考方案1】:

您正在使用 app.config 的架构。每个可执行文件(EXE,而不是 DLL)都有一个 app.config 文件。可执行文件启动,创建其 AppDomain,然后加载 MyApp.exe.config。您可以在 Visual Studio 中随意添加 app.config 对象,但 DLL 会忽略它们。我认为您要做的是手动从 dll.config 复制 XML 并将其粘贴到应用程序级别的 app.config 中。 (我确信有一种方法可以使用 TeamBuild 或类似的方法自动执行此操作。)然后,您的 Properties.Settings 类将可以使用覆盖的值。

【讨论】:

是的,但问题清楚地表明应用程序不应该知道插件设置。 是的,但是如果我可以在运行时以某种方式将插件中的设置动态注入到主 app.config 设置文件中,我会很满意。这里的问题是我还需要插件中 app.config 文件的连接字符串设置章节,因为它们几乎都在 SQL Server 数据库中工作。 如果每个插件都是在其自己的 AppDomain 中创建的(通常这是一个好主意,它会出现在 SO 上的其他帖子中),那么您也许可以说服它为新的 AppContext。 是的,我知道,但是因为我的插件应该能够相互通信(通过使用提供者和消费者插件之间的事件),所以应该序列化,以便能够跨 AppDomain 边界进行通信。 【参考方案2】:

ConfigurationManager.OpenMappedExeConfiguration 之类的东西会在这里提供帮助吗?您可以创建一个从特定文件读取值的配置对象。

【讨论】:

另一个阻碍它工作的问题是你将拥有一个 Configuration 实例,但生成的 Properties.Settings 类仍然无法工作。【参考方案3】:

我更喜欢构建和使用 IConfigManager 类型的插件。它的工作是抽象配置的存储方式。您通过依赖注入收到它的一个实例。这样,IConfigManager 实现可以从多个 .config 文件、网络、数据库或任何其他来源加载设置。我还使用它来提供基于用户、机器和/或应用程序的默认值 - 可以由用户覆盖,例如背景颜色、字体等

此方法的其他优点是可以在所有插件中以一致的方式保留设置 - 无需插件关心,插件存储其设置的位置可以透明地更改(从 .config 到其他),最后,可以在单元测试期间模拟 IConfigManager 以模拟不同的情况。

希望对你有帮助。

【讨论】:

我对这种方法很感兴趣。您能否发布示例或示例链接? 嗨 Rick,我不确定我是否可以在此评论中加入很多示例。我没有指向此答案的任何特定内容的链接 - 如果我有博客,我可以写一篇博客文章。我所说的内容中是否有您想进一步了解的部分?我会看看我是否可以在某个地方建立一个博客并写下这个,但它不会很快。干杯。【参考方案4】:

您可以让每个插件读取它自己的 ConfigurationSection,然后在主配置文件中使用 ConfigSource 设置指向外部文件。 (有关更多信息,请参阅此link)

您并没有完全避免在 app.config 主文件中包含插件配置信息,但至少插件特定设置在单独的文件中。

【讨论】:

【参考方案5】:

我是埃里克的同事。由于他将在接下来的几周内度过一个当之无愧的假期,因此我将详细说明这个问题。

在我们的插件中,我们使用多个 WCF 服务客户端实例。这些服务的巧妙之处在于它们带有 app.config 部分,您可以使用这些部分来配置行为、服务类型、安全性等。

现在,当我们加载插件时,配置中缺少这些部分,因此无法找到正确的端点。当然,我们可以在代码中设置它们,但这会破坏在需要时设置其他配置选项的能力。例如,我们可能想要实现 ws-security。

所以我们需要一种方法来加载这些配置,以便插件可以读取相应的设置。我们当然可以将所有配置合并为一个,但这种方式消除了“仅插件”方法,因为您必须在安装插件的同时管理配置。

我想过创建一个小工具,它将“主”配置与放置在项目子目录中的所有配置合并,并用那个替换 .exe.config 文件。我认为这可行,但我想知道 .NET 是否没有提供更好的选择。多个 AppDomain 不是一个可行的方法,因为插件必须相互交互(提供者/消费者模型),我们不想仅仅因为这个问题而切换到远程处理。

更新:我通过使用 ConfigurationManager 打开现有配置以读取 appSettings 解决了大多数问题。至于 WCF 客户端;您可以在这里找到服务器和客户端的端点/绑定配置:http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx

【讨论】:

您是否知道可以从主 app.config/web.config 引用外部 .config 文件?这样,您可以将插件设置保存在单独的文件中,只需添加对主配置的引用。无论如何,您必须以某种方式注册插件,所以我认为这没什么大不了的。【参考方案6】:

我通常更喜欢通过创建一个专用的 Xml 文件来避免整个 app.config 混乱,主机在该文件中也使用插件的设置进行处理。 Xml 看起来像这样:

<root>
    <Settings>
        Here's where anything specific to the app goes.
    </Settings>
    <plugins>
        <plugin type="mylibrary.myclass">
            Here I let the plugin serialize itself however it wants to.
        </plugin>
    </plugins>
</root>

托管应用然后从 type 属性创建插件并测试该类是否实现 ISerializable;如果是这样,那么插件将自行反序列化。将插件与应用程序的设置内联有点可怕,但是如果您将插件的 Xml 子字符串加载到新的 XmlReader 中,那么您不必担心插件读取时出错在 Xml 字符串中太远了。

【讨论】:

以上是关于插件使用自己的 app.config的主要内容,如果未能解决你的问题,请参考以下文章

没有 App.config 的 SQLite 实体框架

在 Vue 3 的插件中创建全局计算属性

flask蓝图与插件

Flask插件与蓝图

app.config 引用源代码路径而不是 dll 路径

vue3中如何像vue2中注册全局插件