Setara dengan 'app.config' untuk perpustakaan (DLL)

149

Apakah ada yang setara dengan app.configuntuk perpustakaan (DLL)? Jika tidak, apa cara termudah untuk menyimpan pengaturan konfigurasi yang khusus untuk perpustakaan? Harap pertimbangkan bahwa perpustakaan dapat digunakan dalam aplikasi yang berbeda.

Louis Rhys
sumber

Jawaban:

161

Anda dapat memiliki file konfigurasi terpisah, tetapi Anda harus membacanya "secara manual", ConfigurationManager.AppSettings["key"]hanya akan membaca konfigurasi dari unit yang sedang berjalan.

Dengan asumsi Anda menggunakan Visual Studio sebagai IDE Anda, Anda dapat mengklik kanan proyek yang diinginkan → Tambah → Item baru → File Konfigurasi Aplikasi

Ini akan menambah App.configfolder proyek, menempatkan pengaturan Anda di sana di bawah <appSettings>bagian. Jika Anda tidak menggunakan Visual Studio dan menambahkan file secara manual, pastikan untuk memberikannya nama seperti itu: DllName.dll.config , jika tidak, kode di bawah ini tidak akan berfungsi dengan baik.

Sekarang untuk membaca dari file ini memiliki fungsi seperti itu:

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;
}

Dan untuk menggunakannya:

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");
    ...
}

Anda juga harus menambahkan referensi ke namespace System.Configuration agar kelas ConfigurationManager tersedia.

Saat membangun proyek, selain DLL Anda akan memiliki DllName.dll.configfile juga, itu file yang Anda harus publikasikan dengan DLL itu sendiri.

Di atas adalah kode sampel dasar, bagi mereka yang tertarik pada contoh skala penuh, silakan merujuk ke jawaban lain ini .

Shadow Wizard adalah Telinga Untuk Anda
sumber
1
@Rodney coba ubah string exeConfigPath = this.GetType().Assembly.Location;ke sesuatu seperti:string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";
Shadow Wizard adalah Ear For You
1
Adakah yang tahu bagaimana melakukan ini jika dll sedang disalin ke folder yang tidak dikenal oleh alat pengujian unit resharper?
Autodidact
11
Kiat untuk orang lain yang mengimplementasikan ini: untuk mengotomatiskan pembuatan DllName.dll.config dengan mereferensikan aplikasi, saya cukup mengganti nama app.config menjadi DllName.dll.config, dan mengubah properti "Salin ke Keluaran Direktori" menjadi "Salin selalu" . Juga, kebutuhan saya adalah untuk koneksi string, yang dapat diambil dengan menggunakan config.ConnectionStrings.ConnectionStrings [connStringName] .ConnectionString.
Jeff G
2
nama file app.cfg sangat penting untuk membaca nilai appcfg, nama file harus "DLL_NAME.DLL.CONFIG"
SaddamBinSyed
2
Koreksi komentar terakhir saya. Dalam solusi VS2017 saya, dengan menghapus file App.config baru saya yang tidak berfungsi dari proyek uji & DLL saya dan hanya menambahkannya kembali ke proyek pengujian saya, tiba-tiba mulai berfungsi! Pengaturan App.config saya sekarang secara otomatis disertakan dalam DLL.configs. Apa yang lega!
Zeek2
30

Sayangnya, Anda hanya dapat memiliki satu file app.config per executable, jadi jika Anda memiliki DLL yang ditautkan ke aplikasi Anda, mereka tidak dapat memiliki file app.config mereka sendiri.

Solusinya adalah: Anda tidak perlu meletakkan file App.config dalam proyek Perpustakaan Kelas.
Anda meletakkan file App.config di aplikasi yang mereferensikan dll perpustakaan kelas Anda.

Sebagai contoh, katakanlah kita memiliki perpustakaan kelas bernama MyClasses.dll yang menggunakan file app.config seperti:

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

Sekarang, katakanlah kita memiliki Aplikasi Windows bernama MyApp.exe yang mereferensikan MyClasses.dll. Ini akan berisi App.config dengan entri seperti:

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

ATAU

File xml setara dengan yang terbaik untuk app.config. Gunakan xml serialisasi / deserialize sesuai kebutuhan. Anda dapat menyebutnya apa yang Anda inginkan. Jika konfigurasi Anda "statis" dan tidak perlu diubah, Anda juga bisa menambahkannya ke proyek sebagai sumber daya yang disematkan.

Semoga ini memberikan beberapa Ide

Pawan
sumber
6
ConfigurationSettingssekarang sudah usang dan digantikan oleh ConfigurationManager, jadi yang setara sekarang akanConfigurationManager.AppSettings
Gone Coding
2
suara turun. pertanyaannya adalah per dll dan bukan per aplikasi. solusi terbaik: stackoverflow.com/a/5191101/2935383
raiserle
3
Saya menduga saran ini tidak akan bekerja dalam kasus dll dll yang akan memiliki pengetahuan tentang executable memanggil mereka.
beanmf
9

File konfigurasi adalah aplikasi-lingkup dan bukan ruang-perakitan. Jadi, Anda harus meletakkan bagian konfigurasi perpustakaan Anda di file konfigurasi setiap aplikasi yang menggunakan perpustakaan Anda.

Yang mengatakan, itu bukan praktik yang baik untuk mendapatkan konfigurasi dari file konfigurasi aplikasi, khususnya appSettingsbagian, di perpustakaan kelas. Jika pustaka Anda membutuhkan parameter, mereka mungkin harus dilewatkan sebagai argumen metode dalam konstruktor, metode pabrik, dll. Oleh siapa pun yang memanggil pustaka Anda. Ini mencegah panggilan aplikasi dari sengaja menggunakan kembali entri konfigurasi yang diharapkan oleh perpustakaan kelas.

Yang mengatakan, file konfigurasi XML sangat berguna, jadi kompromi terbaik yang saya temukan adalah menggunakan bagian konfigurasi khusus. Anda bisa meletakkan konfigurasi perpustakaan Anda dalam file XML yang secara otomatis dibaca dan diuraikan oleh kerangka kerja dan Anda menghindari potensi kecelakaan.

Anda dapat mempelajari lebih lanjut tentang bagian konfigurasi khusus di MSDN dan juga Phil Haack memiliki artikel yang bagus tentang mereka.

Nyonya0
sumber
7
"Ini bukan praktik yang baik untuk mendapatkan konfigurasi dari file konfigurasi di perpustakaan kelas" - Saya sangat tidak setuju dengan ini. Sebagai contoh, perpustakaan kelas DAL biasanya harus mendapatkan data konfigurasi seperti string koneksi dari file konfigurasi aplikasi daripada meminta informasi ini diteruskan dari tingkat BLL. Setiap kelas Kerangka yang menggunakan konfigurasi (mis. Keanggotaan ASP.NET) berfungsi dengan cara ini.
Joe
Saya sedikit mengubah jawaban saya. Saya masih mendukung apa yang saya katakan, tetapi Anda benar, saya tidak pernah bermaksud menyiratkan bahwa file konfigurasi tidak boleh digunakan sama sekali. Apa yang saya maksudkan adalah, alih-alih berbasis konvensi appSettings, bagian khusus menawarkan alternatif yang bagus; cukup banyak yang digunakan oleh Keanggotaan 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
}

Hanya untuk melakukan sesuatu, saya refactored jawaban teratas ke dalam kelas. Penggunaannya seperti:

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

Jika Anda menambahkan Pengaturan ke proyek Pustaka Kelas di Visual Studio (Properti Proyek, Pengaturan), itu akan menambahkan file app.config ke proyek Anda dengan bagian UserSettings / applyatioNSettings yang relevan, dan nilai-nilai default untuk pengaturan ini dari Pengaturan Anda.pengaturan mengajukan.

Namun file konfigurasi ini tidak akan digunakan saat runtime - sebaliknya perpustakaan kelas menggunakan file konfigurasi aplikasi hostingnya.

Saya percaya alasan utama untuk menghasilkan file ini adalah agar Anda dapat menyalin / menempelkan pengaturan ke file konfigurasi aplikasi host.

Joe
sumber
4

Saat ini saya sedang membuat plugin untuk merek perangkat lunak ritel, yang sebenarnya adalah perpustakaan kelas .net. Sebagai persyaratan, setiap plugin perlu dikonfigurasi menggunakan file konfigurasi. Setelah sedikit riset dan pengujian, saya menyusun kelas berikut. Itu melakukan pekerjaan dengan sempurna. Perhatikan bahwa saya belum menerapkan penanganan pengecualian lokal dalam kasus saya karena, saya menangkap pengecualian di tingkat yang lebih tinggi.

Beberapa penyesuaian mungkin diperlukan untuk mendapatkan titik desimal yang benar, jika desimal dan ganda, tetapi berfungsi dengan baik untuk Info Culture saya ...

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);
    }
}

Contoh file App.Config

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

Pemakaian:

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

Penghargaan untuk Shadow Wizard & MattC

Yiannis Leoussis
sumber
1
Ini harus menjadi jawaban yang diterima. Sangat kompak dan "berfungsi langsung dari kotak". Barang bagus
nmarler
2

Menanggapi pertanyaan awal, saya biasanya menambahkan file konfigurasi dalam proyek pengujian saya sebagai tautan; Anda kemudian dapat menggunakan atribut DeploymentItem untuk menambahkan ke folder Keluar dari uji coba.

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

Menanggapi komentar bahwa Assemblies tidak dapat spesifik proyek, mereka dapat dan itu memberikan fleksibilitas yang luar biasa. saat bekerja dengan kerangka kerja IOC.

Allan Elder
sumber
2

Saya menghadapi masalah yang sama dan menyelesaikannya dengan membuat kelas statis Parameterssetelah menambahkan File Konfigurasi Aplikasi ke proyek:

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;
    }
}

Kemudian dapatkan parameter seperti ini:

Parameters.GetParameter("keyName");
krlzlx
sumber
1
Cemerlang! Ini membantu saya untuk mendapatkan tes otomatis Driver Aplikasi Windows saya berjalan pada mesin target. Dll dalam kasus saya berasal dari proyek uji. Satu-satunya hal yang akan saya tambahkan adalah bahwa di Win App Driver (dan mungkin bentuk pengujian otomatis lainnya), BaseDirectory sebenarnya adalah folder keluaran yang berubah setiap waktu. Saya harus substring seperti ini ... AppDomain.CurrentDomain.BaseDirectory.Substring (0, AppDomain.CurrentDomain.BaseDirectory.IndexOf ("TestResults")). dengan cara ini saya dapat memotong folder keluaran yang tidak diinginkan karena file konfigurasi saya berada di folder yang sama dengan dll pengujian saya.
Ewan
1

majelis tidak memiliki file app.config sendiri. Mereka menggunakan file app.config dari aplikasi yang menggunakannya. Jadi, jika majelis Anda mengharapkan hal-hal tertentu dalam file konfigurasi, maka pastikan file konfigurasi aplikasi Anda memiliki entri-entri di sana.

Jika perakitan Anda digunakan oleh beberapa aplikasi, maka masing-masing aplikasi tersebut harus memiliki entri tersebut di file app.config mereka.

Apa yang saya sarankan Anda lakukan adalah mendefinisikan properti pada kelas dalam perakitan Anda untuk nilai-nilai tersebut misalnya

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;
  }
}

Di sini, properti ExternalServicesUrl mendapatkan nilainya dari file konfigurasi aplikasi. Jika ada aplikasi yang menggunakan rakitan ini tidak memiliki pengaturan dalam file konfigurasi Anda akan mendapatkan pengecualian o Jelas ada sesuatu yang hilang.

MissingConfigFileAppSettings adalah Pengecualian khusus. Anda mungkin ingin melempar pengecualian yang berbeda.

Tentu saja desain yang lebih baik adalah agar metode kelas-kelas tersebut diberikan nilai-nilai tersebut sebagai parameter daripada mengandalkan pengaturan file konfigurasi. Dengan cara itu aplikasi yang menggunakan kelas-kelas ini dapat memutuskan dari mana dan bagaimana mereka memberikan nilai-nilai ini.

Shiv Kumar
sumber
Peringatan di atas: ketika menjalankan tes xUnit pada DLL .NET assembly Anda, xUnit akan membaca perpustakaan .config, saat runtime. Dan itu akan mengabaikan semua App.config yang ditambahkan ke proyek tes atau DLL.
Zeek2
1

Gunakan tambah item yang ada, pilih konfigurasi aplikasi dari proyek dll. Sebelum mengklik add, gunakan panah bawah kecil di sebelah kanan tombol add untuk "add as link"

Saya melakukan ini sepanjang waktu di dev saya.

ghostJago
sumber
1

Pembukaan : Saya menggunakan NET 2.0;

Solusi yang diposting oleh Yiannis Leoussis dapat diterima tetapi saya memiliki beberapa masalah dengannya.

Pertama, static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");pengembalian nol. Saya harus mengubahnya kestatic AppSettingSection = myDllConfig.AppSettings;

Maka return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);tidak memiliki tangkapan untuk Pengecualian. Jadi saya sudah mengubahnya

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

Ini bekerja sangat baik tetapi jika Anda memiliki dll yang berbeda, Anda harus menulis ulang setiap kali kode untuk setiap perakitan. Jadi, ini adalah versi saya untuk Kelas untuk instantiate setiap kali Anda butuhkan.

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);
        }
    }
}

Untuk konfigurasi:

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

Gunakan sebagai:

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
sumber
Harap tinjau suara untuk dihapus. Kesalahan saya adalah mengirim jawaban saat menulisnya.
Matteo Gaggiano
0

Sejauh yang saya ketahui, Anda harus menyalin + menempel bagian yang Anda inginkan dari perpustakaan .config ke dalam aplikasi .config file. Anda hanya mendapatkan 1 app.config per instance yang dapat dieksekusi.

mike
sumber
jika Anda menggunakan bagian konfigurasi khusus, Anda dapat menggunakan atribut configSource: <MySection configSource = "mysection.config" /> dan file konfigurasi hanya menyalin dengan dll.
Jan Remunda
Saya telah menambahkan pertanyaan baru seperti yang ditanyakan, misalnya tentang fungsi, selalu mengembalikan string kosong dan pengaturan server mail> stackoverflow.com/questions/25123544/… dan> stackoverflow.com/questions/25138788/... jadi saya harap seseorang membalasnya seperti saya Saya hampir di tepi hardcoding nilai-nilai ke dalam DLL!
MonkeyMagix
0

Mengapa tidak menggunakan:

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

Anda hanya perlu memperbarui secara visual properti-properti tersebut pada waktu desain melalui:

[Solution Project]->Properties->Settings

Pedro Mora
sumber
Ini secara otomatis akan membuat file konfigurasi untuk dll. Tetapi Anda tidak dapat membaca nilai yang dimodifikasi dari file konfigurasi saat runtime. Akhirnya akan ditampilkan nilai aplikasi panggilan Anda. Lihat juga @Joak jawab
Kode Paus
Tidak jika itu dikonfigurasi untuk konfigurasi pengguna. Idenya adalah untuk mengedit apa yang dibutuhkan pengguna, mengkonfigurasinya saat runtime dan kemudian menyimpannya. Kemudian, ketika pengguna bekerja dengan perpustakaan, itu memuat konfigurasinya, disimpan di jalur pengguna masing-masing, tetapi hanya bekerja untuknya.
Pedro Mora
0

gunakan dari konfigurasi harus sangat sangat mudah seperti ini:

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

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

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

untuk detail lebih lanjut lihat MiniConfig

Rahmat Anjirabi
sumber