πάν*_*ῥεῖ 14 .net c# configuration
我为插件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
Run Code Online (Sandbox Code Playgroud)
保存第一次时生成的.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>
Run Code Online (Sandbox Code Playgroud)
当尝试Config.GetSection()在后续运行时使用此XML加载时,我会ConfigurationErrorsException在XML示例中标记的行中找到,指出MyPlugin无法找到程序集或其中一个依赖项(请原谅我没有发布原始文件)异常消息,但我只有德语,并怀疑这个文本在这里会有所帮助).内部异常来自于System.IO尝试加载程序集并获得反射以解析"MyConfigurationSettings"类类型.
为了精确这种情况,上面的代码放在框架DLL(程序集)中,而框架DLL(程序集)又由从主应用程序加载的实际插件DLL引用.
以下UML图说明了几个组件的关系:

在仔细研究了这个问题之后,我觉得有必要强化名称(签名)导出MyConfigurationSettings类(即PluginFramework)的程序集并将其注册到GAC.我还没有尝试过这个,并且想要避免这一步骤有几个原因(在知道它是否可以帮助之前,它是解决问题的唯一选择).
所以这里有一些问题(对不起,我实际上在这里提出了4个问题,但它们之间的联系非常紧密,因此为它们创建单独的SO问题是没有意义的).
我是否可以通过强有力地命名有问题的程序集并将其注册到GAC来解决定位失败问题?
愚蠢的配置管理抱怨的程序集,保证加载(因为它Configuration.GetSection()自己调用).
是否有可能使用ConfigurationManager或Confguration类显式注册程序集或相应的配置类型de-/serializers ?
我也对有关Hans Passant的评论的更多信息感兴趣,提到这可能是由主应用程序加载(主要)程序集的方式引起的问题.我无法控制这种机制,如果这导致这种行为本身我想知道是否有合理的解决方法?
另一个想法(如果上述任何内容未能显示方法)是本机地完全管理配置XML格式(使用XML解/序列化支持)以及从何处加载和合并配置文件.如果这是最合适的选项,那么任何人都可以给出如何有效地执行此操作(用于管理路径和合并的最不必要的代码)吗?
更新:
由于似乎没有人能够对这个问题给出更多的见解(2个答案并没有让我更进一步),我正在改为4的选项,手动完成所有操作.
我也尝试过,但我从来没有让它像那样工作。我只是认为自动加载 .config 不适用于 .dll,仅适用于 .exe。然后我放弃了,并决定手动加载 .config 文件会更容易。您可以在此处查看完整代码:https://github.com/GeertBellekens/Enterprise-Architect-Toolpack/blob/master/EANavigator/NavigatorSettings.cs 这是最相关的部分:
public NavigatorSettings() {
Configuration roamingConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
// the roamingConfig now get a path such as C:\Users\<user>\AppData\Roaming\Sparx_Systems_Pty_Ltd\DefaultDomain_Path_2epjiwj3etsq5yyljkyqqi2yc4elkrkf\9,_2,_0,_921\user.config
// which I don't like. So we move up three directories and then add a directory for the EA Navigator so that we get
// C:\Users\<user>\AppData\Roaming\GeertBellekens\EANavigator\user.config
string configFileName = System.IO.Path.GetFileName(roamingConfig.FilePath);
string configDirectory = System.IO.Directory.GetParent(roamingConfig.FilePath).Parent.Parent.Parent.FullName;
string newConfigFilePath = configDirectory + @"\Geert Bellekens\EANavigator\" + configFileName;
// Map the roaming configuration file. This
// enables the application to access
// the configuration file using the
// System.Configuration.Configuration class
ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = newConfigFilePath;
// Get the mapped configuration file.
currentConfig = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
// merge the default settings
this.mergeDefaultSettings();
}
Run Code Online (Sandbox Code Playgroud)
访问配置属性:
public bool trackSelectedElement
{
get {
bool result;
if(bool.TryParse(this.currentConfig.AppSettings.Settings["trackSelectedElement"].Value, out result)) {
return result;
}
else {
return true;
}
}
set {
this.currentConfig.AppSettings.Settings["trackSelectedElement"].Value = value.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7262 次 |
| 最近记录: |