2

ConfigurationSection外部のapp.configファイルの構成からコピーを作成しようとしていますが、その最終目標は、実行中のアプリケーションの現在ロードされている構成にマージすることです。

目的は、個々のAppDomainにロードされた多数のライブラリが、実行中のアプリケーションから構成を受け取り、独自のapp.config設定をマージして、設定の読み取りがConfigurationManager.AppSettingsまたはへの単純な呼び出しになるようにすることConfigurationManager.GetSection()です。

私が遭遇している問題は、のクローンを作成することですConfigurationSection

私が試したこと:

  1. ConfigurationSectionClonerエンタープライズライブラリ内。

    Configuration externalConfig = ConfigurationManager.OpenExeConfiguration(externalLibPath);
    var section = externalConfig.GetSection("some.section");
    ConfigurationSectionCloner sectionCloner = new ConfigurationSectionCloner();
    section = sectionCloner.Clone(section);
    
    Configuration localConfig = ConfigurationManager.OpenExecConfiguration(ConfigurationUserLevel.None);
    localConfig.Sections.Add("some.section", section);
    
    • これは正常に実行されますが、両方ともlocalConfig.GetSection("some.section")ConfigurationManager.GetSection("some.section")です。
    • (パラメーターの任意の組み合わせで)呼び出しlocalConfig.Save()ても、セクションにはデータが入力されません。

  2. CompositeConfigurationSourceHandlerエンタープライズライブラリ

    SystemConfigurationSource localConfig = new SystemConfigurationSource();
    FileConfigurationSource externalConfig = new FileConfigurationSource(externalLibPath + ".config");
    CompositeConfigurationSourceHandler ccsh = new CompositeConfigurationSourceHandler(externalConfig);
    ConfigurationSection section = externalConfig.GetSection("some.section");
    if (!ccsh.CheckAddSection("some.section", section)) {
        try {
            localConfig.Add("some.section", section);
        } catch (Exception) { }
    }
    
    • localConfig.add()これにより、という行に例外がスローされCannot add a ConfigurationSection that already belongs to the Configuration.ます。問題は、そのセクションlocalConfig がないことです。追加localConfig.Remove("some.section");しても解決しません。
    • また、オブジェクトのいくつかの組み合わせを試して*ConfigurationSource、違いが生じるかどうかを確認しましたが、違いはありません。

ブロックから実際のApplicationSettingsをコピーすることappSettings、またはブロックからConnectionStringsをコピーすることはconnectionStrings、のような呼び出しでは非常にConfigurationManager.AppSettings.Set("some key", "some value");簡単ですが、ConfigurationSectionsではそれほど簡単ではないようです。

ConfigurationSectionある構成から別の構成にコピー、クローン作成、および/または単純にマージする方法はありますか?

ノート:

  1. 物理ファイルをマージしたくありません。すべては実行時に発生し、メモリ内にのみ残る必要があります。
  2. 各ConfigurationSectionを表すカスタムクラスを作成したくありません。セクションは一般的であり、実行中のアプリケーションには不明です。
4

1 に答える 1

4

ConfigurationSectionapp.configファイルから読み取ったをメインの実行中のアプリケーションにロードされた構成とマージする方法を見つけました!

ConfigurationSectionClonerこのメソッドは、エンタープライズライブラリのを使用して#1のコードを拡張します。

// open the external configuration
Configuration externalConfig = ConfigurationManager.OpenExeConfiguration(externalLibPath);

// get the section we're looking to clone & merge
var sectionToClone = externalConfig.GetSection(sectionName);

// "clone" the section; this will create a `DefaultSection` object - not a "pure clone" =[
ConfigurationSectionCloner sectionCloner = new ConfigurationSectionCloner();
var clonedSection = sectionCloner.Clone(sectionToClone);

// set the `Type` of the new section to the one we're cloning (most likely a NameValueCollection)
clonedSection.SectionInformation.Type = sectionToClone.SectionInformation.Type;

// set the new section's XML to match the original one (really? the cloner doesn't do this?!)
clonedSection.SectionInformation.SetRawXml(sectionToClone.SectionInformation.GetRawXml());

// open our local configuration (the "executing application's config)
Configuration localConfig = ConfigurationManager.OpenExecConfiguration(ConfigurationUserLevel.None);

// add the cloned section to it
localConfig.Sections.Add(sectionName, clonedSection);

// save the section (this can be any variation-of-parameters for `.Save()`)
localConfig.Save(ConfigurationSaveMode.Minimal);

// force ConfigurationManager to refresh the new section
ConfigurationManager.RefreshSection(sectionName);

奇妙なことに、私のすべてのテストでは、上記の手順がすべて必要です。セクションごとに必要な主なものは、新しいセクションのを設定しType、を呼び出しSetRawXml()、セクションを更新することです。

このアプローチの欠点は、私の当初の要望に反して、localConfig.Save()元のapp.configファイルを上書きするディスクに保存するための呼び出しです。複数のAppDomainでこれを非同期に行うと、競合の問題が発生しますが、それは別のトピックです。

于 2013-03-28T01:41:30.387 に答える