.config XMLを格納するプラグインDLLのカスタム構成セクションを、メインの実行可能アプリケーションファイルから作成しました。ここで .NETカスタム設定セクション:Configuration.GetSectionがアセンブリの例外を見つけることができません。
は、カスタムセクションクラスのサンプルです: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はConfig.GetSection()
を使用してロードしようとする
<?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>
その後の実行で、XMLサンプルに記された行にConfigurationErrorsException
というキャッチフレーズがあり、アセンブリMyPlugin
またはそれの依存関係の1つが見つかりませんでした(私が元の例外メッセージを投稿していないことを許してください私はそれをドイツ語でしか持っていないし、このテキストがここで役に立つとは思えない)。内部例外はアセンブリを読み込み、リフレクションを取得して 'MyConfigurationSettings'クラス型を解決しようとしているときにSystem.IO
から発生します。
正確には、上のコードは、メインアプリケーションからロードされた実際のプラグインDLLによって参照されるフレームワークDLL(アセンブリ)内に配置されます。
以下のUML図は、いくつかのコンポーネントの関係を示しています。この問題について少し周りを見た後
を、私はそれが強い名前(記号)MyConfigurationSettings
クラスをエクスポートアセンブリ(すなわちに必要だ感じていますPluginFramework
)、それをGACに登録します。私はまだこれを試していないし、いくつかの理由でこのステップを避けたい(それが助けてくれるかどうかを知る前に、問題を解決する唯一の選択肢です)。
ここに質問があります(申し訳ありませんが、私はここで実際に4つの質問をしていますが、彼らは強く関連しているので、別々の質問があります)。
私は強い疑問にアセンブリを命名し、GACでそれを登録することにより、位置決め不良の問題を解決できますか?
設定管理が不満を抱いているアセンブリは、(それが
Configuration.GetSection()
を呼び出すので)ロードされることが保証されています。
ConfigurationManager
またはConfguration
クラスを使用してアセンブリまたは適切な構成タイプのデシリアライザまたはシリアライザを明示的に登録する方法がありますか?私は、Hans Passant's commentについてさらに詳しく知りたいと考えています。これは、(プライマリ)アセンブリがメインアプリケーションからロードされる方法に起因する問題かもしれないと言及しています。私はこのメカニズムを制御することはできません。これが本質的にこの動作を引き起こす場合は、妥当な回避策があるかどうかを知りたいのですが?
もう1つのアイデア(上記のいずれかが方法を示していない場合)は、構成XMLフォーマットをネイティブに(XMLデシリアライゼーションサポートを使用して)完全に管理し、構成ファイルをどこからロードしてマージするかです。これが最も適切なオプションであれば、どのようにして効率的に(パスとマージを管理するために必要なコードを)行うのか、良い指針を与えることができますか?
更新:誰が(2つの答えは実際にはさらに私を得ることはありません)、この質問(複数可)についての詳細洞察力を与えることができるように思わないので
、私はからオプションに変更しています4.、それをすべて手作業でやってください。
私は確かに言いますが、GACにいる必要はありません。まず、Section Handlerが残りのコードと同じディレクトリに存在することを確認します。次に、正しい構成マネージャーを使用していることを確認します。第3に、すべての{<! - Config properties ... - >}が "MyConfigurationSettings"のプロパティに対応していることを確認してください。これが始まります... そして4番目!あなたのクラスを見て...私はそれを正しく活用しているとは思わない。そこには "GetSection"ではなく、プロパティが必要です。これは、GetSectionを呼び出すフレームワークであり、フレームワークは、-callプロパティを指定する必要がある右セクションハンドラを見つけます。 –
メインアプリケーションが強い名前の場合、参照するアセンブリもすべて厳密な名前でなければなりません。 – groverboy
@ T.S。有望な音!質問を改善するためのいくつかの編集を見てください。前述のフレームワークDLLは、プラグインDLLと同じディレクトリにありますが、メインアプリケーションの実行可能ファイルと同じディレクトリにはありません。私は設定プロパティに関するあなたの意見は無関係かもしれないと思います(少なくともこの特定の例外については、.config XMLでマークした行について正確に文句を言います)。 'GetSection()'メソッドの利用について、これはこのセクションにアクセスするための便宜のために書かれていますが、私はこれをどこで、どのようにしてプロパティに置き換えることができないのでしょうか... –