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


149

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

回答:


161

あなたはできる別の設定ファイルを持っていますが、「手動」それを読む必要があるでしょう、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に加えて、DLL DllName.dll.configとともに公開する必要のあるファイルもファイルに含めます。

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


1
変更してみてください@Rodney string exeConfigPath = this.GetType().Assembly.Location;のようなものに:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";
シャドウウィザードはあなたのための耳で

1
dllがresharperユニットテストツールによって不明なフォルダーにコピーされている場合、これを行う方法はありますか?
Autodidact 2013年

11
これを実装する他の人のためのヒント:アプリケーションを参照してDllName.dll.configの生成を自動化するために、app.configの名前をDllName.dll.configに変更し、[出力ディレクトリにコピー]プロパティを[常にコピー]に変更しました。また、config.ConnectionStrings.ConnectionStrings [connStringName] .ConnectionStringを使用して取得できる接続文字列も必要でした。
Jeff G

2
app.cfgファイル名は、appcfg値を読み取るために非常に重要です。ファイル名は「DLL_NAME.DLL.CONFIG」である必要があります
SaddamBinSyed

2
私の最後のコメントへの訂正。私のVS2017ソリューションでは、テストプロジェクトとDLLプロジェクトから新しい機能していないApp.configファイルを削除し、テストプロジェクトに再度追加するだけで、突然機能し始めます!App.configの設定が自動的にDLL.configsに含まれるようになりました。なんと安心したことでしょう。
Zeek2

30

残念ながら、実行可能ファイルごとに作成できる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を使用します。あなたはそれをあなたが望むすべてのものと呼ぶことができます。構成が「静的」であり、変更する必要がない場合は、組み込みリソースとしてプロジェクトに追加することもできます。

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


6
ConfigurationSettings現在は廃止と置き換えられているConfigurationManager同等のが今ことになるので、ConfigurationManager.AppSettings
コーディングゴーン

2
反対票。問題はdllごとであり、アプリごとではありません。最善の解決策:stackoverflow.com/a/5191101/2935383
レイザー

3
この提案は、実行可能ファイルを呼び出す実行可能ファイルを認識していない遅延バインディングDLLの場合には機能しないと思います。
beanmf 2018

9

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

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

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

あなたは上のカスタム構成セクションについての詳細を学ぶことができMSDNともフィル・ハークは素晴らしいの記事があり、それらのを。


7
「クラスライブラリの構成ファイルから構成を取得することはお勧めしません」-私はこれに強く同意しません。たとえば、DALクラスライブラリは通常、この情報をBLL層から渡すのではなく、アプリケーション構成ファイルから接続文字列などの構成データを取得する必要があります。構成を使用するフレームワーククラス(ASP.NETメンバーシップなど)はすべてこの方法で機能します。
Joe

答えを少し修正しました。私はまだ私が言ったことを支持します、しかしあなたは正しいです、私は構成ファイルがまったく使用されるべきではないことを暗示することを決して意図しませんでした。私が言ったことはappSettings、慣習に基づくの代わりに、カスタムセクションが優れた代替手段を提供するということです。結局のところ、ASP.NETメンバーシップが使用するものとほぼ同じです。
madd0

5
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");

4

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

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

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


4

現在、小売ソフトウェアブランドのプラグインを作成しています。これは実際には.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の功績


1
これは受け入れられる答えになるはずです。非常にコンパクトで「箱から出してすぐに使える」。良いもの
nmarler

2

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

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

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


2

私は同じ問題に直面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
鮮やかさ!これは、ターゲットアプリケーションでWindowsアプリケーションドライバーの自動テストを実行するのに役立ちました。私の場合のdllはテストプロジェクトからのものでした。私が追加する唯一のものは、Win App Driver(およびおそらく他の形式の自動テスト)では、BaseDirectoryが実際に毎回変更される出力フォルダーであることです。私はこのようにサブストリングを作成する必要がありました... AppDomain.CurrentDomain.BaseDirectory.Substring(0、AppDomain.CurrentDomain.BaseDirectory.IndexOf( "TestResults"))。このようにして、私の構成ファイルがテストDLLと同じフォルダーにあったので、不要な出力フォルダーを切り取ることができました。
Ewan

1

アセンブリには、独自の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は、アプリケーションの構成ファイルからその値を取得します。このアセンブリを使用するアプリケーションのいずれかが構成ファイルでその設定を欠いている場合、例外が発生しますo何かが欠落していることは明らかです。

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

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


上記の注意点:.NETアセンブリDLLでxUnitテストを実行すると、xUnitは実行時にライブラリの.configを読み取ります。また、テストプロジェクトまたはDLLプロジェクトに追加されたApp.configは無視されます。
Zeek2

1

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

私はこれをいつも私の開発者の中で行っています。


1

前文: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");

削除の投票を確認してください。私の間違いはそれを書いている間に答えを送ることでした。
Matteo Gaggiano

0

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


カスタム構成セクションを使用している場合は、configSource属性を使用できます:<MySection configSource = "mysection.config" />および構成ファイルはDLLでのみコピー
Jan Remunda

たとえば、常に空の文字列とメールサーバー設定を返す関数> stackoverflow.com/questions/25123544/…と> stackoverflow.com/questions/25138788/…の ように、質問に新しい質問を追加しました。DLLに値をハードコードするだけの端にいます!
MonkeyMagix 2014

0

使用しない理由:

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

デザインタイムにこれらのプロパティを視覚的に更新する必要があります。

[Solution Project]->Properties->Settings


これにより、dllの構成ファイルが自動的に作成されます。ただし、実行時に構成ファイルから変更された値を読み取ることはできません。最後に、呼び出し元のアプリケーションの値が表示されます。@Joeの回答も参照してください
コードポープ

ユーザーの構成用に構成されている場合は、いいえ。アイデアは、ユーザーが必要とするものを編集し、実行時に構成してから保存することです。次に、ユーザーがライブラリを操作すると、ライブラリがその設定をロードし、それぞれのユーザーパスに保存されますが、自分だけが機能します。
ペドロ・モラ

0

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.