Файл конфигурации С# DLL

Я пытаюсь добавить файл app.config в свою DLL, но все попытки потерпели неудачу.

Согласно MusicGenesis в разделе Ввод информации о конфигурации в DLL, это не должно быть проблемой. Поэтому, очевидно, я делаю что-то неправильно...

Следующий код должен вернуть мой ConnectionString из моей DLL:

return ConfigurationManager.AppSettings["ConnectionString"];

Однако, когда я копирую файл app.config в консольное приложение, он отлично работает.

Любые идеи?

Ответ 1

Нетрудно создать файл конфигурации .NET для .DLL и не без оснований. Механизм конфигурации .NET имеет множество встроенных в него функций для упрощения обновления/обновления приложения и защиты установленных приложений от портирования конфигурационных файлов друг друга.

Существует большая разница между тем, как используется DLL и как используется приложение. У вас вряд ли будет несколько копий приложения, установленного на одном компьютере для одного и того же пользователя. Но у вас вполне может быть 100 различных приложений или библиотек, использующих некоторую .NET DLL.

В то время как редко приходится отслеживать настройки отдельно для разных копий приложения в рамках одного профиля пользователя, очень маловероятно, что вы хотите, чтобы все разные способы использования DLL для совместного использования с друг друга. По этой причине, когда вы извлекаете объект "Конфигурация" с использованием "нормального" метода, возвращаемый объект привязывается к конфигурации домена приложения, в котором вы выполняете, а не к конкретной сборке.

Домен приложения привязан к корневой сборке, которая загружает сборку, в которой находится ваш код. В большинстве случаев это будет сборка вашего основного .EXE, загружаемого в .DLL. В приложении можно развернуть другие домены приложений, но вы должны явно предоставить информацию о том, что такое корневая сборка этого домена приложения.

Из-за этого процедура создания конфигурационного файла, специфичного для библиотеки, не очень удобна. Это тот же процесс, который вы использовали бы для создания произвольного портативного файла конфигурации, не связанного с какой-либо конкретной сборкой, но для которого вы хотите использовать схему .NET XML, раздел конфигурации и механизмы элементов конфигурации и т.д. Это влечет за собой создание ExeConfigurationFileMap, погрузка в данные, чтобы определить, где будет храниться файл конфигурации, а затем вызвать ConfigurationManager. OpenMappedExeConfiguration, чтобы открыть его в новый экземпляр Configuration. Этот будет отключен от защиты версии, предлагаемой механизмом автоматической генерации пути.

По статистике, вы, вероятно, используете эту библиотеку в домашней обстановке, и маловероятно, что у вас будет несколько приложений, использующих ее в рамках любой машины/пользователя. Но, если нет, есть что-то, о чем вы должны помнить. Если вы используете один глобальный файл конфигурации для своей DLL, независимо от приложения, которое ссылается на него, вам нужно беспокоиться о конфликтах доступа. Если одновременно запускаются два приложения, ссылающиеся на вашу библиотеку, каждый из которых имеет свой собственный объект Configuration, то при сохранении изменений он будет вызывать исключение в следующий раз при попытке получить или сохранить данные в другом приложении.

Самый безопасный и простой способ обойти это - потребовать, чтобы сборка, которая загружает вашу DLL, также предоставляет некоторую информацию о себе или обнаруживает ее, исследуя домен приложения реферирующей сборки. Используйте это, чтобы создать некоторую структуру папок для хранения отдельных пользовательских конфигурационных файлов для каждого приложения, ссылающегося на вашу DLL.

Если вы определенно, вы хотите иметь глобальные настройки для своей DLL независимо от того, где он ссылается, вам нужно будет определить ваше местоположение для него, а не .NET, автоматически определяя соответствующий, Вам также необходимо быть агрессивным в управлении доступом к файлу. Вам нужно будет кэшировать как можно больше, поддерживая экземпляр Configuration только ТОЛЬКО, пока он загружается или сохраняется, сразу же открывая и удаляя. И, наконец, вам понадобится механизм блокировки для защиты файла, когда он редактируется одним из приложений, которые используют библиотеку.

Ответ 2

если вы хотите прочитать настройки из файла конфигурации DLL, но не из корневых приложений web.config или app.config, используйте ниже код для чтения конфигурации в dll.

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

Ответ 3

У меня была такая же проблема, и я искал в Интернете несколько часов, но я не мог найти решения, поэтому я сделал свой собственный. Я задавался вопросом, почему система конфигурации .net настолько негибкая.

Справочная информация. Я хочу, чтобы у моего DAL.dll был свой собственный файл конфигурации для настроек базы данных и DAL. Мне также нужен app.config для Enterprise Library и его собственных конфигураций. Поэтому мне нужны как app.config, так и dll.config.

То, что я не хотел делать, - это передать все свойства/настройки из приложения в мой слой DAL!

для изгибания "AppDomain.CurrentDomain.SetupInformation.ConfigurationFile" невозможно, потому что мне нужно его для обычного поведения app.config.

Мои требования/точки зрения:

  • НЕТ ручной копии чего-либо из класса ClassLibrary1.dll.config в WindowsFormsApplication1.exe.config, потому что это неприемлемо для других разработчиков.
  • сохранить сильную типизацию "Properties.Settings.Default.NameOfValue" (поведение настроек), потому что я думаю, что это основная функция, и я не хотел ее потерять.
  • Я обнаружил отсутствие ApplicationSettingsBase для ввода собственного/настраиваемого файла конфигурации или управления (все необходимые поля являются частными в этих классах)
  • использование перенаправления файлов "configSource" невозможно, потому что нам нужно будет скопировать/переписать ClassLibrary1.dll.config и предоставить несколько файлов XML для нескольких разделов (мне также это не понравилось)
  • Мне не нравилось писать свой собственный SettingsProvider для этой простой задачи, поскольку MSDN предлагает, потому что я думал, что просто будет слишком много.
  • Мне нужны только разделы applicationSettings и connectionStrings из файла конфигурации

Я придумал модифицировать файл Settings.cs и реализовал метод, который открывает ClassLibrary1.dll.config и читает информацию раздела в частном поле. После этого я переопределил это [string propertyName], чтобы сгенерированные параметры Settings.Desginer.cs вызывали в мое новое свойство вместо базового класса. Там параметр считывается из Списка.

Наконец, существует следующий код:

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 из выходного каталога ClassLibrary1 в каталог вывода вашего приложения. Возможно, кто-то найдет это полезным.

Ответ 4

При использовании ConfigurationManager я уверен, что он загружает файл конфигурации процесса / AppDomain (app.config/web.config). Если вы хотите загрузить определенный файл конфигурации, вам нужно будет запросить этот файл по имени...

Вы можете попробовать:

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

Ответ 5

ConfigurationManager.AppSettings возвращает параметры, определенные для приложения, а не для конкретной DLL, вы можете получить к ним доступ, но это параметры приложения, которые будут возвращены.

Если вы используете вашу dll из другого приложения, то ConnectionString будет в app.settings приложения.

Ответ 6

Я знаю, что опаздывать на вечеринку, однако я думал, что поделюсь решением, которое я использую для DLL.

Я больше отношусь к K.I.S.S. школа мышления, поэтому, когда у меня есть .NET DLL, которая хочет хранить внешние точки данных, которые контролируют, как она работает или куда она идет, и т.д. Я просто создаю класс "config", который имеет только общедоступные свойства, которые хранят все точки данных он нужен и что я хотел бы иметь возможность контролировать внешний доступ к DLL, чтобы не перекомпилировать его для внесения изменений. Затем я использую .Net XML Serializing для сохранения и загрузки объектного представления класса в файл.

Есть много способов обработать его чтение и доступ к нему, от Singleton, статического класса утилиты, до методов расширения и т.д. Это зависит от того, как структурирована ваша библиотека DLL и какой метод лучше всего подходит вашей DLL.

Ответ 7

Похоже, что эти конфигурационные файлы действительно запутывают, чтобы пояснить, как их поведение изменяется от среды dev до развертывания. По-видимому, DLL может иметь свой собственный файл конфигурации, но как только вы скопируете и вставьте DLL (вместе с их конфигурационным файлом) в другое место, все это перестало работать. Единственное решение состоит в том, чтобы вручную объединить файлы app.config в один файл, который будет использоваться только exec. Напр. В myapp.exe будет файл myapp.exe.config, содержащий все настройки для всех dll, используемых myapp.exe. Я использую VS 2008.

Kenny Liew

Ответ 8

вы правы, вы можете прочитать конфигурационный файл dll. Я боролся с этим в течение дня, пока не узнал, что мой файл конфигурации был проблемой. См. Мой код ниже. он смог запустить.

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

my Plugin1.dll.config выглядел ниже:

<?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>

Я узнал, что в моем файле конфигурации не было тега <appSettings>, поэтому оглянитесь вокруг, ваша проблема может быть другой, но не так уж далека от моей.

Ответ 9

Поскольку сборка находится во временном кэше, вы должны объединить этот путь, чтобы получить конфигурацию dll:

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

Ответ 10

Я нашел то, что кажется хорошим решением этой проблемы. Я использую VS 2008 С#. Мое решение подразумевает использование различных пространств имен между несколькими конфигурационными файлами. Я разместил решение в своем блоге: http://tommiecarter.blogspot.com/2011/02/how-to-access-multiple-config-files-in.html.

Например:

Это пространство имен для чтения/записи настроек dll:

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

Это пространство имен считывает/записывает настройки exe:

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

В статье упоминаются некоторые оговорки. НТН

Ответ 11

Если вы используете библиотеки, которые просматривают большое количество закулисных закулисных объектов, таких как WCF, вы можете подумать об этом:

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

Или в PowerShell:

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

IMO этот метод является запахом кода и действительно подходит только для использования в ad hoc-скриптах. Если вы захотите сделать это в производственном коде, возможно, это время для архитектурного обзора.

НЕ рекомендуется:
Как техническое любопытство, здесь вариация на тему. Вы можете создать статический конструктор внутри одного из классов, размещенных в DLL, и выполнить этот вызов оттуда. Я бы не рекомендовал делать это, кроме как в крайнем случае.

Ответ 12

Как говорит Марк, это невозможно (хотя Visual Studio позволяет добавить файл конфигурации приложения в проект библиотеки классов).

Возможно, вы захотите проверить класс AssemblySettings, который, по-видимому, делает файлы конфигурации сборки возможными.

Ответ 14

Для dll он не должен зависеть от конфигурации, так как конфигурация принадлежит приложению, а не dll.

Это объясняется в здесь

Ответ 15

вы можете использовать этот код:

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

Ответ 16

Полное решение не часто встречается в одном месте...

1) Создайте файл конфигурации приложения и назовите его "yourDllName.dll.config"
2) Щелкните правой кнопкой мыши на файле конфигурации, созданном выше в VS Solution Explorer, щелкните свойства
--- установите "Build Action" = Содержимое
--- установите "Копировать в каталог вывода" = Всегда
3) Добавьте раздел appSettings в файл конфигурации (yourDllName.dll.config) с вашим именем yourKeyName и yourKeyValue

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

4) Добавьте System.Configuration в свои ссылки dll/class/project

5) Добавьте операторы using в свой код, где вы хотите получить доступ к настройке конфигурации

using System.Configuration;
using System.Reflection;

6) Чтобы получить доступ к значению

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

7) радуйся, он работает

IMHO, это следует использовать только при разработке новой библиотеки dll/library.

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

Конфигурационный файл становится отличной ссылкой, когда вы добавляете dll appSettings в свое фактическое приложение.