我为插件 DLL 创建了一个自定义配置部分,它将 .config XML 存储在一个单独的(来自主可执行应用程序)文件中。
这是自定义部分类的示例:
using System;
using System.Configuration;
namespace PluginFramework.MyConfiguration
{
public class MyConfigurationSettings : ConfigurationSection
{
private Configuration _Config = null;
#region ConfigurationProperties
/// <summary>
/// A custom XML section for an application's configuration file.
/// </summary>
[ConfigurationProperty("MyProjects", IsDefaultCollection = true)]
public MyProjectConfigurationCollection MyProjects
{
get { return (MyProjectConfigurationCollection) base["MyProjects"]; }
}
// ...
#endregion
/// <summary>
/// Private Constructor used by our factory method.
/// </summary>
private MyConfigurationSettings () : base () {
// Allow this section to be stored in user.app. By default this is forbidden.
this.SectionInformation.AllowExeDefinition =
ConfigurationAllowExeDefinition.MachineToLocalUser;
}
// ...
#region Static Members
/// <summary>
/// Gets the current applications <MyConfigurationSettings> section.
/// </summary>
/// <param name="ConfigLevel">
/// The <ConfigurationUserLevel> that the config file
/// is retrieved from.
/// </param>
/// <returns>
/// The configuration file's <MyConfigurationSettings> section.
/// </returns>
public static MyConfigurationSettings GetSection (ConfigurationUserLevel ConfigLevel)
{
string appDataPath = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string localDataPath = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
System.Configuration.ExeConfigurationFileMap exeMap = new ExeConfigurationFileMap();
exeMap.ExeConfigFilename = System.IO.Path.Combine(appDataPath, @"MyCompany\MyPluginApp\Default.config");
exeMap.RoamingUserConfigFilename = System.IO.Path.Combine(appDataPath, @"MyCompany\MyPluginApp\Roaming.config");
exeMap.LocalUserConfigFilename = System.IO.Path.Combine(localDataPath, @"MyCompany\MyPluginApp\Local.config");
System.Configuration.Configuration Config = ConfigurationManager.OpenMappedExeConfiguration(exeMap,ConfigLevel);
MyConfigurationSettings myConfigurationSettings = null;
try {
myConfigurationSettings = (MyConfigurationSettings)Config.GetSection("MyConfigurationSettings");
}
catch (System.Exception ex) {
// ConfigurationErrorsException caught here ...
}
if (myConfigurationSettings == null) {
myConfigurationSettings = new MyConfigurationSettings();
Config.Sections.Add("MyConfigurationSettings", myConfigurationSettings); }
}
if(myConfigurationSettings != null) {
myConfigurationSettings._Config = Config;
}
return myConfigurationSettings;
}
#endregion
}
} // PluginFramework.MyConfiguration
第一次保存时生成的 .config XML 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- The exception complains about the following line (assembly attributes are compliant): -->
<section name="MyConfigurationSettings" type="PluginFramework.MyConfiguration.MyConfigurationSettings, PluginFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" allowDefinition="Everywhere" allowExeDefinition="MachineToLocalUser" />
</configSections>
<MyConfigurationSettings>
<!-- Config properties are serialized fine according MyConfigurationSettings
properties marked with the ConfigurationProperty attribute ... -->
<MyProjects>
<MyProjectConfiguration GUID="{4307AC92-8180-4686-9322-830312ED59AB}">
<!-- ... more complex configuration elements -->
</MyProjectConfiguration>
</MyProjects>
</MyConfigurationSettings>
</configuration>
当尝试Config.GetSection()
在后续运行中加载此 XML 时,我ConfigurationErrorsException
在 XML 示例中标记的行中捕获一个,说明MyPlugin
无法找到程序集或其依赖项之一(请原谅我没有发布原始异常消息,但我只有德语,并且怀疑此文本在这里会有所帮助)。内部异常来自System.IO
尝试加载程序集并获得反射以解析“MyConfigurationSettings”类类型。
为了准确起见,上面的代码被放置在一个框架 DLL(程序集)中,而后者又被从主应用程序加载的实际插件 DLL 引用。
下面的 UML 图说明了几个组件的关系:
在环顾了一下这个问题之后,我觉得有必要对导出MyConfigurationSettings
类(即PluginFramework
)的程序集进行强命名(签名)并将其注册到 GAC。我还没有尝试过,并且出于几个原因想避免这一步(在知道它是否甚至可以帮助之前,这是解决问题的唯一选择)。
所以这里是问题(抱歉,我实际上在这里提出了 4 个问题,但它们之间的关系非常密切,因此为它们创建单独的 SO 问题是没有意义的)。
我可以通过强命名有问题的程序集并将其注册到 GAC 来解决定位失败问题吗?
配置管理抱怨的程序集很愚蠢,保证被加载(因为它调用
Configuration.GetSection()
自己)。
有没有办法用ConfigurationManager
orConfguration
类显式注册程序集或适当的配置类型反序列化器?我也对有关Hans Passant 评论的更多信息感兴趣,他提到这可能是由从主应用程序加载(主)程序集的方式引起的问题。我无法控制这种机制,如果这会导致这种行为,我想知道是否有合理的解决方法?
另一个想法(如果上述任何方法都无法显示)是完全管理配置 XML 格式(使用 XML 反序列化支持)以及从何处加载和合并配置文件。如果这是最合适的选择,任何人都可以给出如何有效地做到这一点的好的指导(管理路径和合并的最少必要代码)?
更新:
由于似乎没有人能够对这个问题提供更多见解(2个答案并没有真正让我进一步了解),所以我从 4. 更改为选项,手动完成所有操作。