Bir kitaplık için 'app.config' öğesine eşdeğerdir (DLL)


149

app.configKitaplıklar (DLL) için bir eşdeğeri var mı ? Değilse, bir kitaplığa özgü yapılandırma ayarlarını depolamanın en kolay yolu nedir? Lütfen kütüphanenin farklı uygulamalarda kullanılabileceğini düşünün.

Yanıtlar:


161

Sen edebilirsiniz ayrı konfigürasyon dosyası var, ancak, "elle" okumak gerekecek ConfigurationManager.AppSettings["key"]montaj çalışan tek yapılandırma okuyacaktır.

IDE'niz olarak Visual Studio kullandığınızı varsayarsak, istediğiniz projeyi sağ tıklayabilirsiniz → Ekle → Yeni öğe → Uygulama Yapılandırma Dosyası

Bu App.configproje klasörüne ekleyecek , ayarlarınızı <appSettings>bölümün altına yerleştireceksiniz . Visual Studio'yu kullanmıyorsanız ve dosyayı el ile eklemiyorsanız , bu adı verdiğinizden emin olun: DllName.dll.config , aksi takdirde aşağıdaki kod düzgün çalışmaz.

Şimdi bu dosyadan okumak için böyle bir işlevi var:

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

Ve kullanmak için:

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 sınıfının kullanılabilir olması için System.Configuration ad alanına da başvuru yapmanız gerekir.

Projeyi oluştururken, DLL'e ek olarak DllName.dll.configdosyaya da sahip olacaksınız , DLL'in kendisiyle yayınlamak zorunda olduğunuz dosya budur.

Yukarıdaki temel örnek kod, tam ölçekli bir örnekle ilgilenenler için lütfen bu diğer cevaba bakınız .


1
@ Rodney string exeConfigPath = this.GetType().Assembly.Location;gibi bir şeye değiştirmeyi deneyin :string exeConfigPath = @"C:\MyFolder\DllFolder\ExeName.exe";
Gölge Sihirbazı Sizin İçin

1
Dll yeniden birleştirici birim test aracı tarafından bazı bilinmeyen bir klasöre kopyalanıyorsa, bunu nasıl bir fikir?
Autodidact

11
Bunu uygulayan herkes için bir ipucu: uygulamalara başvurarak DllName.dll.config neslini otomatikleştirmek için, app.config dosyasını DllName.dll.config olarak yeniden adlandırdım ve "Çıktı Dizine Kopyala" özelliğini "Her zaman kopyala" olarak değiştirdim . Ayrıca, benim ihtiyaç config.ConnectionStrings.ConnectionStrings [connStringName] .ConnectionString kullanılarak alınabilir bağlantı dizeleri için oldu.
Jeff G

2
app.cfg dosya adı appcfg değerlerini okumak için çok önemlidir, dosya adı "DLL_NAME.DLL.CONFIG" olmalıdır
SaddamBinSyed

2
Son yorumuma düzeltme. VS2017 çözümümde, yeni, çalışmayan App.config dosyalarımı test ve DLL projelerimden kaldırarak ve test projeme tekrar ekleyerek aniden çalışmaya başlıyor! App.config ayarım artık otomatik olarak DLL.configs dosyasına ekleniyor. Ne rahatlama!
Zeek2

30

Ne yazık ki, yürütülebilir dosya başına yalnızca bir app.config dosyanız olabilir, bu nedenle uygulamanıza bağlı DLL'leriniz varsa, kendi app.config dosyalarına sahip olamazlar.

Çözüm: App.config dosyasını Sınıf Kitaplığı projesine koymanız gerekmez.
App.config dosyasını sınıf kitaplığınızın dll'sine başvuran uygulamaya koydunuz.

Örneğin, app.config dosyasını kullanan MyClasses.dll adlı bir sınıf kütüphanemiz olduğunu varsayalım:

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

Şimdi, diyelim ki MyClasses.dll dosyasını referans alan bir Windows Uygulamamız var. Bir giriş içeren bir App.config içerir:

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

VEYA

Bir xml dosyası app.config için en iyi eşdeğerdir. Gerektiğinde xml serialize / deserialize komutunu kullanın. İstediğiniz her şeyi diyebilirsiniz. Yapılandırmanız "statik" ise ve değiştirilmesi gerekmiyorsa, bunu projeye katıştırılmış kaynak olarak da ekleyebilirsiniz.

Umarım biraz fikir verir


6
ConfigurationSettingsartık kullanılmıyor ve yerini alıyor ConfigurationManager, yani eşdeğer olacakConfigurationManager.AppSettings
Gone Coding

2
aşağı oy. soru dll başına ve uygulama başına değil. en iyi çözüm: stackoverflow.com/a/5191101/2935383
raiserle

3
Bu öneri onları çalıştırılabilir yürütülebilir hakkında hiçbir bilgiye sahip geç bağlı dll durumunda işe yaramaz şüpheli.
beanmf

9

Yapılandırma dosyaları uygulama kapsamlıdır ve montaj kapsamı kapsamaz. Bu nedenle, kitaplığınızın yapılandırma bölümlerini kitaplığınızı kullanan her uygulamanın yapılandırma dosyasına koymanız gerekir.

Bununla birlikte, uygulamanın appSettingssınıf dosyasındaki yapılandırma bölümünden, özellikle de bölümden yapılandırma almak iyi bir uygulama değildir . Kütüphanenizin parametrelere ihtiyacı varsa, muhtemelen kütüphanenizi çağıran tarafından yapıcılarda, fabrika yöntemlerinde vb. Yöntem bağımsız değişkenleri olarak geçirilmelidir. Bu, çağrı yapılan uygulamaların, sınıf kitaplığı tarafından beklenen yapılandırma girdilerini yanlışlıkla yeniden kullanmasını önler.

Bununla birlikte, XML yapılandırma dosyaları son derece kullanışlıdır, bu yüzden bulduğum en iyi uzlaşma özel yapılandırma bölümlerini kullanmaktır. Kitaplığınızın yapılandırmasını, çerçeve tarafından otomatik olarak okunan ve ayrıştırılan bir XML dosyasına koyarsınız ve olası kazalardan kaçınırsınız.

Üzerinde Özel yapılandırma bölümler hakkında daha fazla bilgi edinebilir MSDN ve ayrıca Phil Haack güzel bir makale vardır onlara.


7
"sınıf kitaplığındaki bir yapılandırma dosyasından yapılandırma almak için iyi bir uygulama değildir" - Buna kesinlikle katılmıyorum. Örneğin, bir DAL sınıf kitaplığı normalde bu bilginin BLL katmanından geçirilmesi yerine bağlantı dizeleri gibi yapılandırma verilerini uygulama yapılandırma dosyasından almalıdır. Yapılandırmayı kullanan tüm Framework sınıfları (örn. ASP.NET Üyeliği) bu şekilde çalışır.
Joe

Cevabımı biraz değiştirdim. Hala söylediklerimin yanındayım, ama haklısın, yapılandırma dosyalarının hiç kullanılmaması gerektiğini ima etmeyi hiç istemedim. Demek istediğim, kurallara dayalı appSettingsözel bölümler yerine özel bölümlerin harika bir alternatif sunmasıydı; sonuçta ASP.NET Üyeliği ne kullanır.
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
}

Sadece bir şeyler yapmak için, en iyi cevabı bir sınıfa tekrar yansıttım. Kullanımı şöyle bir şeydir:

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

4

Visual Studio'da (Kütüphane Özellikleri, Ayarlar) bir Sınıf Kitaplığı projesine Ayarlar eklerseniz, ilgili userSettings / applicatioNSettings bölümlerini ve bu ayarların varsayılan değerlerini Settings.settings öğelerinizle birlikte bir app.config dosyası ekler. dosya.

Ancak bu yapılandırma dosyası çalışma zamanında kullanılmaz - bunun yerine sınıf kitaplığı barındırma uygulamasının yapılandırma dosyasını kullanır.

Bu dosyayı oluşturmanın ana nedeninin ayarları kopyalayıp ana uygulamanın yapılandırma dosyasına yapıştırabilmeniz olduğuna inanıyorum.


4

Şu anda bir perakende yazılım markası için aslında .net sınıfı kütüphaneleri olan eklentiler oluşturuyorum. Gerektiğinde, her eklentinin bir yapılandırma dosyası kullanılarak yapılandırılması gerekir. Biraz araştırma ve testten sonra, aşağıdaki sınıfı derledim. İşi kusursuz yapıyor. Benim durumumda yerel özel durum işleme uygulanmadığımı unutmayın, çünkü daha yüksek düzeyde özel durumlar yakalarım.

Ondalık basamakları ve çiftler durumunda ondalık noktayı doğru yapmak için bazı ayarlamalar gerekebilir, ancak CultureInfo'm için iyi çalışır ...

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 dosyası örneği

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

Kullanımı:

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

Gölge Sihirbazı ve MattC Kredileri


1
Bu kabul edilen cevap olmalı. Çok kompakt ve "kutudan çıkar çıkmaz çalışır". İyi şeyler
nmarler

2

Orijinal soruya yanıt olarak, genellikle test projeme yapılandırma dosyasını bir bağlantı olarak eklerim; daha sonra test çalıştırmasının Out klasörüne eklemek için DeploymentItem özniteliğini kullanabilirsiniz.

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

Montajların projeye özgü olamayacağı yorumlarına yanıt olarak, büyük esneklik sağlar. IOC çerçeveleri ile çalışırken.


2

Aynı sorunla karşılaştım Parametersve projeye bir Uygulama Yapılandırma Dosyası ekledikten sonra statik bir sınıf oluşturarak çözdüm :

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

Sonra böyle bir parametre alın:

Parameters.GetParameter("keyName");

1
Parlak! Bu, Windows Uygulama Sürücüsü otomatik testlerimi hedef makinelerde çalıştırmamı sağladı. Benim durumumdaki dll'ler bir test projesindendi. Ekleyeceğim tek şey, Win App Driver'da (ve muhtemelen diğer otomatik test formlarında), BaseDirectory'nin aslında her seferinde değişen çıktı klasörü olmasıdır. Bunun gibi alt dize gerekiyordu ... AppDomain.CurrentDomain.BaseDirectory.Substring (0, AppDomain.CurrentDomain.BaseDirectory.IndexOf ("TestResults")). Bu şekilde, yapılandırma dosyam test dll'lerle aynı klasörde olduğu gibi istenmeyen çıktı klasörünü kesebilirdim.
Ewan

1

derlemelerin kendi app.config dosyaları yoktur. Bunları kullanan uygulamanın app.config dosyasını kullanırlar. Derlemeniz config dosyasında belirli şeyler bekliyorsa, uygulamanızın config dosyasında bu girdilerin bulunduğundan emin olun.

Derlemeniz birden çok uygulama tarafından kullanılıyorsa, bu uygulamaların her birinin app.config dosyasında bu girişlere sahip olması gerekir.

Yapmanızı tavsiye ettiğim, bu değerler için derlemenizdeki sınıflardaki özellikleri tanımlamaktır.

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

Burada, ExternalServicesUrl özelliği değerini uygulamanın yapılandırma dosyasından alır. Bu derlemeyi kullanan herhangi bir uygulama yapılandırma dosyasında bu ayarı kaçırırsa bir istisna elde edersiniz o bir şey eksik gitti açıktır.

MissingConfigFileAppSettings özel bir İstisnadır. Farklı bir istisna atamak isteyebilirsiniz.

Elbette, bu sınıfların yönteminin, yapılandırma dosyası ayarına güvenmek yerine, bu değerleri parametre olarak sağlaması daha iyi bir tasarım olacaktır. Bu şekilde bu sınıfları kullanan uygulamalar bu değerleri nereden ve nasıl sağladıklarına karar verebilirler.


Yukarıdakilere dikkat edin: .NET derleme DLL'inizde xUnit testleri çalıştırırken, xUnit çalışma zamanında kütüphanenin .config dosyasını okuyacaktır. Ayrıca, sınama veya DLL projesine eklenen tüm App.config dosyalarını yok sayar.
Zeek2

1

Mevcut öğeyi ekle'yi kullanın, dll projesinden uygulama yapılandırmasını seçin. Ekle'yi tıklamadan önce, "bağlantı olarak ekle" yi eklemek için ekle düğmesinin sağ tarafındaki küçük aşağı oku kullanın

Bunu her zaman geliştiricimde yaparım.


1

önsöz : NET 2.0 kullanıyorum;

Gönderen çözüm Yiannis Leoussis kabul edilebilir, ancak bununla ilgili bir sorunum vardı.

İlk önce static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings"); döndürür null. Değiştirmek zorunda kaldımstatic AppSettingSection = myDllConfig.AppSettings;

O zaman return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);İstisnalar için bir yakalama yok. Bu yüzden değiştirdim

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

Bu çok iyi çalışıyor ama farklı bir dll varsa her derleme için kodu her zaman yeniden yazmak zorunda. Yani, bu, bir Sınıfın her ihtiyacınız olduğunda örneklemem için kullandığım versiyonudur.

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

Bir yapılandırma için:

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

Şu şekilde kullanın:

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

Lütfen silmek için oylamayı gözden geçirin. Benim hatam cevabı yazarken göndermekti.
Matteo Gaggiano

0

Bildiğim kadarıyla, kütüphane .config dosyasından istediğiniz bölümleri uygulamalar .config dosyasına kopyalayıp yapıştırmanız gerekir. Her yürütülebilir örnek için yalnızca 1 app.config alırsınız.


özel yapılandırma bölümleri kullanıyorsanız configSource özniteliğini kullanabilirsiniz: <MySection configSource = "mysection.config" /> ve yapılandırma dosyası yalnızca dll ile kopyalanır
Jan Remunda

Örneğin her zaman boş bir dize ve posta sunucusu ayarları döndüren işlev hakkında sorulan yeni sorular ekledim> stackoverflow.com/questions/25123544/… ve> stackoverflow.com/questions/25138788/… Bu yüzden umarım birisi onlara yanıt veriyor neredeyse sadece DLL değerleri sabit kodlama kenarında değilim!
MonkeyMagix

0

Neden kullanmıyorsunuz:

  • [ProjectNamespace].Properties.Settings.Default.[KeyProperty] C # için
  • My.Settings.[KeyProperty] VB.NET için

Bu özellikleri tasarım zamanında görsel olarak güncellemeniz yeterlidir:

[Solution Project]->Properties->Settings


Bu otomatik olarak dll için bir yapılandırma dosyası oluşturur. Ancak değiştirilen değerleri çalışma zamanında yapılandırma dosyasından okuyamazsınız. Son olarak, çağıran uygulamanızın değerlerini gösterecektir. Ayrıca bkz. @Joe answer
Code Pope

Kullanıcının yapılandırması için yapılandırılmışsa hayır. Fikir, kullanıcının ihtiyaç duyduğu şeyleri düzenlemek, çalışma zamanında yapılandırmak ve sonra kaydetmek. Daha sonra, kullanıcı kütüphaneyle çalıştığında, kendi kullanıcı yoluna kaydedilen yapılandırmasını yükler, Ama sadece onun için çalışır.
Pedro Mora

0

konfigürasyonlardan kullanım şu şekilde çok kolay olmalıdır:

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

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

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

daha fazla ayrıntı için bkz. MiniConfig

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.