C # DLL yapılandırma dosyası


191

DLL'ime bir app.config dosyası eklemeye çalışıyorum, ancak tüm denemeler başarısız oldu.

' Yapılandırma bilgilerini bir DLL dosyasına koyma' bölümündeki MusicGenesis'e göre bu bir sorun olmamalı. Açıkçası yanlış bir şey yapıyorum ...

Aşağıdaki kod DLL'imden benim ConnectionString dönmelidir:

return ConfigurationManager.AppSettings["ConnectionString"];

Ancak, app.config dosyasını konsol uygulamama kopyaladığımda iyi çalışıyor.

Herhangi bir fikir?


Belirtilen gönderiye göre: dll adı MyDll.dll ise, yapılandırma dosyası MyDLL.dll.config olmalıdır. Yapılandırma ayarlarını dll içinden okursanız, kendi yapılandırma hakkına başvurmalıdır.
MegaByte

11
Hangi kodun sorduğu önemli değil - AppDomain için belirtildiği gibi dosyayı arıyor: AppDomain.CurrentDomain.SetupInformation.ConfigurationFile ayarı
Marc Gravell

Not: "Yapılandırma bilgilerini bir DLL'e yerleştirme" sorusu, uygulamanızın yapılandırma kodunu ana uygulama kodundan ayrı tutmak için bir kitaplığa ayırmakla ilgilidir. Bu, kendi başına bir DLL için ayrı ve özel bir yapılandırma dosyasından çok farklıdır.
Chris Ammerman


Yanıtlar:


277

Bir .DLL için ve iyi bir nedenle bir .NET yapılandırma dosyası oluşturmak önemsiz değildir. .NET yapılandırma mekanizması, uygulamanın kolay yükseltilmesini / güncellenmesini kolaylaştırmak ve yüklü uygulamaları birbirlerinin yapılandırma dosyalarını ezmeye karşı korumak için yerleşik birçok özelliğe sahiptir.

Bir DLL'in nasıl kullanıldığı ve bir uygulamanın nasıl kullanıldığı arasında büyük bir fark vardır. Aynı kullanıcı için aynı makinede bir uygulamanın birden çok kopyasının yüklü olması olası değildir. Ancak, bazı .NET DLL'leri kullanan 100 farklı uygulama veya kütüphaneye sahip olabilirsiniz.

Bir kullanıcı profili içinde bir uygulamanın farklı kopyalar için ayrı ayrı ayarları izlemek için bir ihtiyaç nadiren var iken, bu kadar çok birbirinize payı yapılandırmasına bir DLL farklı kullanımlar tüm isteyeyim olası. Bu nedenle, "normal" yöntemini kullanarak bir Yapılandırma nesnesi aldığınızda, geri aldığınız nesne, belirli bir montajdan ziyade yürütmekte olduğunuz Uygulama Alanının yapılandırmasına bağlanır.

Uygulama Etki Alanı, kodunuzun içinde bulunduğu derlemeyi yükleyen kök derlemeye bağlıdır. Çoğu durumda bu, .DLL'yi yükleyen ana .EXE'nizin derlemesi olacaktır. Bir uygulama içindeki diğer uygulama alanlarını genişletmek mümkündür, ancak bu uygulama etki alanının kök derlemesinin ne olduğu hakkında açıkça bilgi vermelisiniz.

Tüm bunlar nedeniyle, kitaplığa özgü bir yapılandırma dosyası oluşturma yordamı çok uygun değil. Size herhangi bir montaj bağlı değildir keyfi taşınabilir yapılandırma dosyası oluşturmak için kullanmak istiyorsunuz aynı süreçtir, ancak kendisi için bölüm ve yapılandırma elemanı mekanizmaları vb bir oluştururken bunun şartlarına config, .NET'in XML şemasının yararlanmak isteyen ExeConfigurationFileMapnesneyi , yapılandırma dosyasının nerede saklanacağını belirlemek için verilere yüklenir ve ardından çağrılır ConfigurationManager. OpenMappedExeConfigurationyeni bir Configurationörneğe açmak için . Bu olacak otomatik yol nesil mekanizması tarafından sunulan versiyon korumasından kesti.

İstatistiksel olarak konuşursak, muhtemelen bu kütüphaneyi şirket içi bir ortamda kullanıyorsunuz ve herhangi bir makine / kullanıcı içinde onu kullanan birden fazla uygulamanız olması pek olası değil. Ama değilse, aklınızda bulundurmanız gereken bir şey var. DLL'niz için başvuruda bulunan uygulamadan bağımsız olarak tek bir genel yapılandırma dosyası kullanırsanız, erişim çakışmaları hakkında endişelenmeniz gerekir. Kitaplığınıza başvuran iki uygulama aynı anda çalışıyorsa, her biri kendi Configurationnesnesi açıksa, biri değişiklikleri kaydettiğinde, diğer uygulamada veri almaya veya kaydetmeye çalıştığınızda bir istisnaya neden olur.

Bu sorunu aşmanın en güvenli ve en basit yolu, DLL'nizi yükleyen derlemenin kendisi hakkında da bazı bilgiler sağlamasını veya başvuru derlemesinin Uygulama Etki Alanı'nı inceleyerek bunu belirlemektir. DLL'nize başvuran her uygulama için ayrı kullanıcı yapılandırma dosyaları tutmak amacıyla bir tür klasör yapısı oluşturmak için bunu kullanın.

Eğer varsa bazı bunu başvuruda bulunulan yerde olursa olsun DLL için genel ayarları yapmak istiyorsanız, bunun için konumunuzu belirlemek yerine NET daha otomatik bir uygun olanı bulmaktan gerekir. Dosyaya erişimi yönetme konusunda da agresif olmanız gerekir. Mümkün olduğunca önbelleğe almanız gerekir, Configurationörneğin SADECE yükleme veya kaydetme süresi kadar önce saklayın, hemen önce açın ve hemen sonra atın. Son olarak, kitaplığı kullanan uygulamalardan biri tarafından düzenlenirken dosyayı korumak için bir kilit mekanizmasına ihtiyacınız olacaktır.


Senkronizasyon mekanizmasının "adlandırılmış bir olay" vb. olması gerektiğini düşünüyorum, çünkü süreçler arası
Jacob

8
: / Meh. Bizimki farklı bir zaman dilimi ve çeşitli DLL'ler tarafından temsil edilen modüller tarafından yazılan ve dinamik olarak özel bir eklenti çerçevesi ile bağlı ana .exe w / bir canavar kurumsal app. Tüm bu "birden fazla uygulama aynı anda DLL kullanabilirsiniz emin olmak gerekir" pomposity tam olarak yanlış.
JohnL4

Ayrıca, kariyerimin büyük bir bölümünde, bu güzel genel paylaşılan nesne mekanizmalarının tamamen göz ardı edildiğini gördüm, ekipler yalnızca bir bağlamda kullanılabilecek (ve mevcut olmalı veya uygulama başarısız oluyor) DLL (veya JAR) oluşturuyor ). Statik olarak da bağlı olabilirler, ancak bu passe.
JohnL4

1
"İstatistiksel olarak konuşursak, muhtemelen bu kütüphaneyi şirket içi bir ortamda kullanıyorsunuz ve herhangi bir makinede / kullanıcıda onu kullanan birden fazla uygulamanız olması pek mümkün değil." Teori ve pratik arasındaki fark bazen beni oldukça huysuz ediyor.
JohnL4

1
@Panzercrisis, Visual Studio'nun Settings.settings özelliği otomatik olarak tüm kullanıcı ayarları için sürüme özel yollar oluşturur. Bkz. Stackoverflow.com/questions/35778528/…
Deantwo

101

ayarları dll'nin yapılandırma dosyasından okumak, ancak kök uygulamaları web.config veya app.config'den okumak istemiyorsanız, dll'deki yapılandırmayı okumak için aşağıdaki kodu kullanın.

var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;

VS 2008 için yönetilen C ++ sisteminde :: Configuration :: Configuration ^ appConfig = ConfigurationManager :: OpenExeConfiguration (Assembly :: GetExecutingAssembly () -> Konum); Dize ^ name = appConfig-> AppSettings-> Ayarlar ["ad"] -> Değer;
Hans

Teşekkürler, bu gerçekten sorunumu çözdü. Bu konuyla yaklaşık iki gündür uğraşıyorum ve şimdiye kadar işe yaramadı. Bir hata ayıklama testi sırasında ConfigurationManager makineden okuyordu.
yopez83

19

Aynı sorunu yaşadım ve birkaç saat boyunca web'de arama yaptım, ancak herhangi bir çözüm bulamadım, bu yüzden kendim yaptım. .Net yapılandırma sisteminin neden bu kadar esnek olmadığını merak ettim.

Arka plan: Veritabanı ve DAL ayarları için kendi yapılandırma dosyasına sahip benim DAL.dll sahip olmak istiyorum. Ayrıca Enterprise Library ve kendi yapılandırmaları için app.config dosyasına ihtiyacım var. Bu yüzden hem app.config hem de dll.config dosyasına ihtiyacım var.

Yapmak istemediğim şey, uygulamadan DAL katmanıma her özellik / ayarı geçmek!

"AppDomain.CurrentDomain.SetupInformation.ConfigurationFile" 'i bükmek mümkün değil çünkü normal app.config davranışı için ihtiyacım var.

Gereksinimlerim / bakış açılarım:

  • ClassLibrary1.dll.config dosyasından WindowsFormsApplication1.exe.config dosyasındaki hiçbir şeyin el ile kopyalanması, çünkü bu diğer geliştiriciler için yeniden oluşturulamaz.
  • "Properties.Settings.Default.NameOfValue" (Ayarlar davranışı) gibi güçlü yazmanın kullanımını koruyun, çünkü bunun önemli bir özellik olduğunu düşünüyorum ve kaybetmek istemedim
  • Kendi / özel yapılandırma dosyanızı veya yönetimini enjekte etmek için ApplicationSettingsBase eksikliğini öğrendim (tüm gerekli alanlar bu sınıflarda özeldir)
  • ClassLibrary1.dll.config dosyasını kopyalamak / yeniden yazmak ve birkaç bölüm için birkaç XML dosyası sağlamak zorunda kaldığımız için "configSource" dosya yönlendirmesinin kullanılması mümkün değildir (bunu da beğenmedim)
  • MSDN'nin önerdiği gibi bu basit görev için kendi SettingsProvider'ımı yazmak istemedim çünkü bunun çok fazla olacağını düşündüm
  • Yalnızca config dosyasındaki applicationSettings ve connectionStrings bölümlerine ihtiyacım var

Settings.cs dosyasını değiştirerek gelip ClassLibrary1.dll.config dosyasını açan ve özel bir alandaki bölüm bilgilerini okuyan bir yöntem uyguladım. Bundan sonra, oluşturulan Settings.Desginer.cs temel sınıf yerine benim yeni özelliği çağırır böylece "bu [string propertyName]" geçersiz kıldım. Burada ayar Listeden okunur.

Son olarak aşağıdaki kod vardır:

internal sealed partial class Settings
{
    private List<ConfigurationElement> list;

    /// <summary>
    /// Initializes a new instance of the <see cref="Settings"/> class.
    /// </summary>
    public Settings()
    {
        this.OpenAndStoreConfiguration();
    }

    /// <summary>
    /// Opens the dll.config file and reads its sections into a private List of ConfigurationElement.
    /// </summary>
    private void OpenAndStoreConfiguration()
    {
        string codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
        Uri p = new Uri(codebase);
        string localPath = p.LocalPath;
        string executingFilename = System.IO.Path.GetFileNameWithoutExtension(localPath);
        string sectionGroupName = "applicationSettings";
        string sectionName = executingFilename + ".Properties.Settings";
        string configName = localPath + ".config";
        ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
        fileMap.ExeConfigFilename = configName;
        Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

        // read section of properties
        var sectionGroup = config.GetSectionGroup(sectionGroupName);
        var settingsSection = (ClientSettingsSection)sectionGroup.Sections[sectionName];
        list = settingsSection.Settings.OfType<ConfigurationElement>().ToList();

        // read section of Connectionstrings
        var sections = config.Sections.OfType<ConfigurationSection>();
        var connSection = (from section in sections
                           where section.GetType() == typeof(ConnectionStringsSection)
                           select section).FirstOrDefault() as ConnectionStringsSection;
        if (connSection != null)
        {
            list.AddRange(connSection.ConnectionStrings.Cast<ConfigurationElement>());
        }
    }

    /// <summary>
    /// Gets or sets the <see cref="System.Object"/> with the specified property name.
    /// </summary>
    /// <value></value>
    public override object this[string propertyName]
    {
        get
        {
            var result = (from item in list
                         where Convert.ToString(item.ElementInformation.Properties["name"].Value) == propertyName
                         select item).FirstOrDefault();
            if (result != null)
            {
                if (result.ElementInformation.Type == typeof(ConnectionStringSettings))
                {
                    return result.ElementInformation.Properties["connectionString"].Value;
                }
                else if (result.ElementInformation.Type == typeof(SettingElement))
                {
                    return result.ElementInformation.Properties["value"].Value;
                }
            }
            return null;
        }
        // ignore
        set
        {
            base[propertyName] = value;
        }
    }

ClassLibrary1.dll.config dosyasını ClassLibrary1 çıktı dizininden uygulamanızın çıktı dizinine kopyalamanız gerekir. Belki birisi bunu yararlı bulacaktır.


14

ConfigurationManager'ı kullanırken, işlem / AppDomainyapılandırma dosyasını (app.config / web.config) yüklediğinden eminim . Belirli bir yapılandırma dosyasını yüklemek istiyorsanız, o dosyayı özellikle adıyla istemeniz gerekir ...

Deneyebilirsiniz:

var config = ConfigurationManager.OpenExeConfiguration("foo.dll");
config.ConnectionStrings. [etc]

Belirtilen gönderiye göre: dll adı MyDll.dll ise, yapılandırma dosyası MyDLL.dll.config olmalıdır. Yapılandırma ayarlarını dll içinden okursanız, kendi yapılandırma hakkına başvurmalıdır.
MegaByte

1
Hayır ... sanmıyorum. "dll ile gelen" hiçbir şüphe etmez; varsayılan olarak, AppDomain için tanımlanan yapılandırma dosyasına bakar: my.exe.config
Marc Gravell

1
Özellikle, AppDomain.CurrentDomain.SetupInformation.ConfigurationFile ayarı.
Marc Gravell

Not: OpenExeConfiguration'ı denedim ve çalıştığından da emin değilim. Belki de yapılandırmayı app.config ile birleştirin?
Marc Gravell

Bu olabilir ancak bir EXE app.config dosyası olarak destek ve güvenlik aynı tür ... yapılabilir. Cevabımı gör.
Chris Ammerman

13

ConfigurationManager.AppSettings belirli bir DLL için değil, uygulama için tanımlanan ayarları döndürür, bunlara erişebilirsiniz, ancak döndürülecek uygulama ayarlarıdır.

Eğer başka bir uygulamadan dll kullanıyorsanız o zaman ConnectionString uygulamanın app.settings içinde olacaktır.


6

Bu partiye geç olduğunu biliyorum, ancak ben DLL için kullandığım çözümü paylaşmak istiyorum düşündüm.

Ben daha KISS düşünce okulu değilim, bu yüzden nasıl çalıştığını veya nereye gittiğini kontrol eden dış veri noktalarını saklamak isteyen bir .NET DLL var, vb Sadece basitçe sadece ortak özellikleri olan bir "config" sınıfı oluşturmak gerekli tüm veri noktalarını depolamak ve değişiklikleri yapmak için yeniden derleme önlemek için DLL harici kontrol edebilmek istiyorum. Sonra kaydetmek ve sınıfın nesne gösterimini bir dosyaya yüklemek için .Net'in XML Serileştirme kullanın.

O zaman bir Singleton, statik bir yardımcı sınıf, uzantısı yöntemleri, vb okuma ve erişim işlemek için bir çok yol vardır. Bu DLL nasıl yapılandırılmış ve hangi yöntemi DLL en uygun olacaktır bağlıdır.


Bu yaklaşımı da kullanıyorum ve şimdiye kadarki çalışma şeklinden memnunum.
Dave

4

doğru, bir dll yapılandırma dosyasını okuyabilirsiniz. Ben benim yapılandırma dosyası sorun olduğunu bulana kadar bir gün boyunca bu mücadele etti. Aşağıdaki koduma bakın. koşabildi.

        ExeConfigurationFileMap map = new ExeConfigurationFileMap();
        map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
        Configuration libConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
        AppSettingsSection section = (libConfig.GetSection("appSettings") as AppSettingsSection);
        Console.WriteLine(section.Settings["dnd_shortcodes"].Value);

benim Plugin1.dll.configaşağıdaki gibi görünüyordu;

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <appSettings>
  <add key="cmd_location" value="http://..."/>
  <add key="dnd_shortcodes" value="142,145,146,157,165,167,168,171,173,176,178,404,40"/>
 </appSettings>
</configuration>

Yapılandırma dosyamın <appSettings>etikette olmadığını öğrendim , bu yüzden etrafınıza bakın, sorununuz farklı olabilirdi ancak benimkinden çok uzak değil.


3

Derleme geçici bir önbellekte bulunduğundan, dll'nin yapılandırmasını almak için yolu birleştirmelisiniz:

var appConfig = ConfigurationManager.OpenExeConfiguration(
    Path.Combine(Environment.CurrentDirectory, Assembly.GetExecutingAssembly().ManifestModule.Name));

"Path.Combine (Environment.CurrentDirectory, Assembly.GetExecutingAssembly (). ManifestModule.Name)" yerine "Assembly.GetExecutingAssembly (). Konum" kullanabilirsiniz
Cadburry

3

WCF gibi perde arkasında büyük miktarda yapılandırma arayan kitaplıklar kullanıyorsanız, bunu yapmayı düşünebilirsiniz:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "MyWcfClientWrapper.dll.config");

Veya PowerShell'de:

[AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "MyWcfClientWrapper.dll.config")

IMO bu teknik bir kod kokusudur ve gerçekten sadece geçici komut dosyalarında kullanım için uygundur. Kendinizi bunu üretim kodunda yapmak istiyorsanız, belki de mimari bir inceleme zamanı.

Aşağıdakiler önerilmez:
Teknik bir merak olarak, tema üzerinde bir varyasyon var. DLL'de barındırılan sınıflardan birinin içinde statik bir kurucu oluşturabilir ve bu çağrıyı oradan yapabilirsiniz. Son çare olarak bunu tavsiye etmem.


3

Tam çözüm genellikle tek bir yerde bulunamadı ...

1) Bir uygulama yapılandırma dosyası oluşturun ve buna "yourDllName.dll.config" adını verin.
2) VS Solution Explorer'da yukarıda oluşturulan yapılandırma dosyasına sağ tıklayın, özellikleri tıklayın
--- set "Build Action" = İçerik
--- set "Çıktı Dizine Kopyala" = Her Zaman
3 )KeyName ve KeyKalue'nuz ile yapılandırma dosyasına (yourDllName.dll.config) bir appSettings bölümü ekleyin

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="yourKeyName" value="yourKeyValue"/>
  </appSettings>
</configuration>

4) dll / class / project referanslarınıza System.Configuration ekleyin
5) config ayarlarına erişmek istediğiniz kodunuza using ifadelerini ekleyin

using System.Configuration;
using System.Reflection;

6) Değere erişmek için

string keyValue = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings.Settings["yourKeyName"].Value;

7) sevinir, çalışır

IMHO, bu sadece yeni bir dll / kütüphane geliştirirken kullanılmalıdır.

#if (DEBUG && !FINALTESTING)
   string keyValue = ConfigurationManager.OpenExeConfiguration...(see 6 above)
#else
   string keyValue = ConfigurationManager.AppSettings["yourKeyName"];
#endif

Yapılandırma dosyası, gerçek uygulamanıza dll'nin appSettings'ini eklediğinizde büyük bir referans olur.


3

Görünüşe göre bu yapılandırma dosyaları davranışları geliştirici ortamından konuşlandırmaya değiştikçe açıklığa kavuşmak için kafa karıştırıcı. Görünüşe göre bir DLL kendi yapılandırma dosyası olabilir, ancak dll (yapılandırma dosyası ile birlikte) başka bir yere kopyalayıp yapıştırdıktan sonra, her şey çalışmayı durdurdu. Tek çözüm, app.config dosyalarını yalnızca exec tarafından kullanılacak tek bir dosyada manuel olarak birleştirmektir. Örneğin, myapp.exe, myapp.exe tarafından kullanılan tüm dll'ler için tüm ayarları içeren bir myapp.exe.config dosyasına sahip olacaktır. VS 2008 kullanıyorum.


2

Bu konuda iyi bir çözüm gibi görünen bir şey buldum. VS 2008 C # kullanıyorum. Çözümüm, birden çok yapılandırma dosyası arasında farklı ad alanlarının kullanılmasını içerir. Çözümü bloguma gönderdim: http://tommiecarter.blogspot.com/2011/02/how-to-access-multiple-config-files-in.html .

Örneğin:

Bu ad alanı dll ayarlarını okur / yazar:

var x = company.dlllibrary.Properties.Settings.Default.SettingName;
company.dlllibrary.Properties.Settings.Default.SettingName = value;

Bu ad alanı exe ayarlarını okur / yazar:

company.exeservice.Properties.Settings.Default.SettingName = value;
var x = company.exeservice.Properties.Settings.Default.SettingName;

Makalede bahsedilen bazı uyarılar var. HTH


1

Marc'ın dediği gibi, bu mümkün değildir (Visual Studio bir sınıf kütüphanesi projesine bir uygulama yapılandırma dosyası eklemenize izin verir).

Assembly yapılandırma dosyalarını mümkün kılan AssemblySettings sınıfına göz atmak isteyebilirsiniz .



0

Bir dll için, yapılandırma dll'ye değil yapılandırmaya ait olduğu için yapılandırmaya bağlı olmamalıdır.

Bu burada açıklanıyor


0

bu kodu kullanabilirsiniz:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace GClass1
{
[Guid("D6F88E95-8A27-4ae6-B6DE-0542A0FC7039")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface _GesGasConnect
{
    [DispId(1)]
    int SetClass1Ver(string version);


}

[Guid("13FE32AD-4BF8-495f-AB4D-6C61BD463EA4")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("InterfacesSMS.Setting")]
public class Class1 : _Class1
{
    public Class1() { }


    public int SetClass1(string version)
    {
        return (DateTime.Today.Day);
    }
}
}
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.