web-dev-qa-db-ja.com

ライブラリ(DLL)の「app.config」に相当

ライブラリ(DLL)のapp.configに相当するものはありますか?そうでない場合、ライブラリ固有の構成設定を保存する最も簡単な方法は何ですか?ライブラリは異なるアプリケーションで使用される可能性があることを考慮してください。

136
Louis Rhys

あなたはcan個別の設定ファイルを持っていますが、「手動で」読む必要があります。ConfigurationManager.AppSettings["key"]は実行中のアセンブリの設定のみを読み込みます。

IDEとしてVisual Studioを使用している場合、目的のプロジェクトを右クリック→追加→新しい項目→アプリケーション構成ファイル

これにより、プロジェクトフォルダーにApp.configが追加され、<appSettings>セクションの下に設定が追加されます。 Visual Studioを使用せずにファイルを手動で追加する場合は、次のような名前を付けてください:DllName.dll.config、それ以外の場合、以下のコードは正しく機能しません。

このファイルから読み取るには、次の機能があります。

string GetAppSetting(Configuration config, string key)
{
    KeyValueConfigurationElement element = config.AppSettings.Settings[key];
    if (element != null)
    {
        string value = element.Value;
        if (!string.IsNullOrEmpty(value))
            return value;
    }
    return string.Empty;
}

そしてそれを使用するには:

Configuration config = null;
string exeConfigPath = this.GetType().Assembly.Location;
try
{
    config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception ex)
{
    //handle errror here.. means DLL has no sattelite configuration file.
}

if (config != null)
{
    string myValue = GetAppSetting(config, "myKey");
    ...
}

また、ConfigurationManagerクラスを使用可能にするには、System.Configuration名前空間への参照を追加する必要があります。

プロジェクトをビルドすると、DLLに加えてDllName.dll.configファイルも作成されます。これは、DLL自体で公開する必要のあるファイルです。

上記は基本的なサンプルコードです。フルスケールの例に興味がある場合は、 この他の回答 を参照してください。

148
Shadow Wizard

残念ながら、実行ファイルごとにapp.configファイルは1つしか持てません。そのため、アプリケーションにDLLがリンクされている場合、独自のapp.configファイルを持つことはできません。

解決策:クラスライブラリのプロジェクトにApp.configファイルを配置する必要はありません。
クラスライブラリのdllを参照しているアプリケーションにApp.configファイルを配置します。

たとえば、次のようにapp.configファイルを使用するMyClasses.dllという名前のクラスライブラリがあるとします。

string connect = 
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];

ここで、MyClasses.dllを参照するMyApp.exeという名前のWindowsアプリケーションがあるとします。次のようなエントリを持つApp.configが含まれます。

<appSettings>
    <add key="MyClasses.ConnectionString"
         value="Connection string body goes here" />
</appSettings>

または

Xmlファイルはapp.configに最適です。必要に応じてxml serialize/deserializeを使用します。必要なものをすべて呼び出すことができます。設定が「静的」で、変更する必要がない場合は、埋め込みリソースとしてプロジェクトに追加することもできます。

それがいくつかのアイデアを与えることを願っています

26
PawanS

構成ファイルは、アプリケーションスコープであり、アセンブリスコープではありません。したがって、ライブラリを使用しているすべてのアプリケーションの構成ファイルにライブラリの構成セクションを配置する必要があります。

ただし、クラスライブラリのアプリケーションの構成ファイル(特にappSettingsセクション)から構成を取得することはお勧めできません。ライブラリにパラメータが必要な場合は、ライブラリを呼び出す人がコンストラクタ、ファクトリメソッドなどのメソッド引数として渡す必要があります。これにより、呼び出し側のアプリケーションが、クラスライブラリが予期していた構成エントリを誤って再利用することを防ぎます。

そうは言っても、XML構成ファイルは非常に便利なので、私が見つけた最良の妥協点は、カスタム構成セクションを使用することです。ライブラリの構成をフレームワークによって自動的に読み取られて解析されるXMLファイルに入れることで、潜在的な事故を回避できます。

MSDN および Phil HaackにはNice article でカスタム構成セクションの詳細を学ぶことができます。

8
madd0
public class ConfigMan
{
    #region Members

    string _assemblyLocation;
    Configuration _configuration;

    #endregion Members

    #region Constructors

    /// <summary>
    /// Loads config file settings for libraries that use Assembly.dll.config files
    /// </summary>
    /// <param name="assemblyLocation">The full path or UNC location of the loaded file that contains the manifest.</param>
    public ConfigMan(string assemblyLocation)
    {
        _assemblyLocation = assemblyLocation;
    }

    #endregion Constructors

    #region Properties

    Configuration Configuration
    {
        get
        {
            if (_configuration == null)
            {
                try
                {
                    _configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
                }
                catch (Exception exception)
                {
                }
            }
            return _configuration;
        }
    }

    #endregion Properties

    #region Methods

    public string GetAppSetting(string key)
    {
        string result = string.Empty;
        if (Configuration != null)
        {
            KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key];
            if (keyValueConfigurationElement != null)
            {
                string value = keyValueConfigurationElement.Value;
                if (!string.IsNullOrEmpty(value)) result = value;
            }
        }
        return result;
    }

    #endregion Methods
}

何かするために、私はトップの答えをクラスにリファクタリングしました。使用法は次のようなものです。

ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
5
Firegarden

現在、実際には.netクラスライブラリである小売ソフトウェアブランドのプラグインを作成しています。要件として、構成ファイルを使用して各プラグインを構成する必要があります。少しの調査とテストの後、次のクラスをコンパイルしました。それは完璧に仕事をします。私の場合、ローカルの例外処理を実装していないことに注意してください。なぜなら、より高いレベルで例外をキャッチするからです。

小数と倍数の場合、小数点を正しくするために微調整が必​​要になる場合がありますが、CultureInfoでは正常に機能します...

static class Settings
{
    static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
    static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);
    static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
    static NumberFormatInfo nfi = new NumberFormatInfo() 
    { 
        NumberGroupSeparator = "", 
        CurrencyDecimalSeparator = "." 
    };

    public static T Setting<T>(string name)
    {
        return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
    }
}

App.Configファイルのサンプル

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

使用法:

  somebooleanvar = Settings.Setting<bool>("Enabled");
  somestringlvar = Settings.Setting<string>("ExportPath");
  someintvar =     Settings.Setting<int>("Seconds");
  somedoublevar =  Settings.Setting<double>("Ratio");

Shadow WizardおよびMattCのクレジット

3

Visual Studioのクラスライブラリプロジェクト(プロジェクトプロパティ、設定)に設定を追加すると、関連するuserSettings/applicatioNSettingsセクションと、Settings.settingsのこれらの設定のデフォルト値を使用してapp.configファイルがプロジェクトに追加されます。ファイル。

ただし、この構成ファイルは実行時に使用されません。代わりに、クラスライブラリはホストアプリケーションの構成ファイルを使用します。

このファイルを生成する主な理由は、ホストアプリケーションの構成ファイルに設定をコピーして貼り付けることができるためだと思います。

3
Joe

元の質問に対する回答として、通常はテストプロジェクトに構成ファイルをリンクとして追加します。その後、DeploymentItem属性を使用して、テスト実行のOutフォルダーに追加できます。

[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
    .
    .
    .
    .
}

アセンブリーはプロジェクト固有ではないというコメントに応えて、それは可能であり、特に柔軟性に優れています。 IOCフレームワークを使用する場合。

2
Allan Elder

アセンブリには独自のapp.configファイルがありません。それらは、それらを使用しているアプリケーションのapp.configファイルを使用します。そのため、アセンブリが構成ファイルに特定のものを期待している場合は、アプリケーションの構成ファイルにそれらのエントリがあることを確認してください。

アセンブリが複数のアプリケーションで使用されている場合、それらの各アプリケーションはapp.configファイルにこれらのエントリを含める必要があります。

私がお勧めすることは、たとえば、それらの値のアセンブリのクラスでプロパティを定義することです

private string ExternalServicesUrl
{
  get
  {
    string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"];
    if (String.IsNullOrEmpty(externalServiceUrl))
      throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl");
    return externalServiceUrl;
  }
}

ここで、プロパティExternalServicesUrlは、アプリケーションの構成ファイルからその値を取得します。このアセンブリを使用しているアプリケーションに設定ファイルの設定が欠けている場合、例外が発生します。何かが足りないことは明らかです。

MissingConfigFileAppSettingsはカスタム例外です。別の例外をスローすることもできます。

もちろん、構成ファイルの設定に依存するのではなく、これらのクラスのメソッドにこれらの値をパラメーターとして提供することをお勧めします。これにより、これらのクラスを使用するアプリケーションは、これらの値をどこからどのように提供するかを決定できます。

1
Shiv Kumar

私は同じ問題に直面し、プロジェクトにアプリケーション構成ファイルを追加した後に静的クラスParametersを作成することで解決しました。

public static class Parameters
{
    // For a Web Application
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config");

    // For a Class Library
    public static string PathConfig { get; private set; } =
        Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config");

    public static string GetParameter(string paramName)
    {
        string paramValue = string.Empty;

        using (Stream stream = File.OpenRead(PathConfig))
        {
            XDocument xdoc = XDocument.Load(stream);

            XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName);
            paramValue = element.Attribute("value").Value;
        }

        return paramValue;
    }
}

次に、次のようなパラメーターを取得します。

Parameters.GetParameter("keyName");
1
krlzlx

既存のアイテムの追加を使用して、dllプロジェクトからアプリの構成を選択します。 [追加]をクリックする前に、追加ボタンの右側にある小さな下矢印を使用して[リンクとして追加]

私はこれを開発者で常に行っています。

1
ghostJago

プリアンブル:私はNET 2.0を使用しています;

Yiannis Leoussis が投稿した解決策は受け入れられますが、問題がありました。

まず、static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");はnullを返します。 static AppSettingSection = myDllConfig.AppSettings;に変更する必要がありました

その場合、return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);には例外のキャッチがありません。だから私はそれを変更しました

try
{
    return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
    return default(T);
}

これは非常にうまく機能しますが、異なるdllがある場合は、すべてのアセンブリのコードを毎回書き直す必要があります。だから、これはあなたが必要とするたびにインスタンス化するクラスの私のバージョンです。

public class Settings
{
    private AppSettingsSection _appSettings;
    private NumberFormatInfo _nfi;

    public Settings(Assembly currentAssembly)
    {
        UriBuilder uri = new UriBuilder(currentAssembly.CodeBase);
        string configPath = Uri.UnescapeDataString(uri.Path);
        Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath);
        _appSettings = myDllConfig.AppSettings;
        _nfi = new NumberFormatInfo() 
        { 
            NumberGroupSeparator = "", 
            CurrencyDecimalSeparator = "." 
        };
    }


    public T Setting<T>(string name)
    {
        try
        {
            return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi);
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }
}

構成の場合:

<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />

次のように使用します。

Settings _setting = new Settings(Assembly.GetExecutingAssembly());

somebooleanvar = _settings.Setting<bool>("Enabled");
somestringlvar = _settings.Setting<string>("ExportPath");
someintvar =     _settings.Setting<int>("Seconds");
somedoublevar =  _settings.Setting<double>("Ratio");
1
Matteo Gaggiano

構成からの使用は、次のように非常に簡単でなければなりません。

var config = new MiniConfig("setting.conf");

config.AddOrUpdate("port", "1580");

if (config.TryGet("port", out int port)) // if config exist
{
    Console.Write(port);
}

詳細については、 MiniConfig を参照してください

0
Rahmat Anjirabi

使用しない理由:

  • C#の[ProjectNamespace].Properties.Settings.Default.[KeyProperty]
  • VB.NETのMy.Settings.[KeyProperty]

設計時にこれらのプロパティを視覚的に更新する必要があります:

[Solution Project]->Properties->Settings

0
Pedro Mora

私の知る限り、必要なセクションをライブラリ.configからアプリケーションの.configファイルにコピーして貼り付ける必要があります。実行可能インスタンスごとに1つのapp.configのみを取得します。

0
mike