Settings.Default. <property>всегда возвращает значение по умолчанию вместо значения в постоянном хранилище (файл XML) - PullRequest
10 голосов
/ 10 октября 2008

Я недавно написал DLL на C # (.Net 2.0), которая содержит класс, который требует IP-адрес. Мой коллега изменил класс для получения IP-адреса из файла «.dll.config» (XML) - очевидно, он автоматически генерируется созданным им файлом «Настройки приложения» (Settings1.settings). Преимущество этого состояло в том, что конечный пользователь мог по своему желанию изменять IP-адрес в файле XML / config.

К сожалению, когда я проверяю его код в дереве и пытаюсь скомпилировать (или использовать) этот новый код, любое приложение, вызывающее эту DLL, получает только значение по умолчанию, а не значение из файла.

Конструктор, который вызывает файл конфигурации, выглядит следующим образом:

    public class form : System.Windows.Forms.Form
    {
        public form()
        {
            // This call is required by the Windows Form Designer.
            InitializeComponent();
            IP = IPAddress.Parse(Settings1.Default.IPAddress);
        }
    }

Я нашел ссылку на эту проблему на форумах MSDN , где пользователь сказал:

«старые» значения (те, которые вы определяете во время разработки) жестко запрограммированы. Если franework не может получить доступ к файлу конфигурации или открыть его, вместо него будут использоваться значения по умолчанию. Это всегда будет происходить, если вы используете настройки в DLL.

  1. Означает ли это, что я не могу сохранить внешнее значение для DLL в файле конфигурации? (Мой сотрудник как-то сделал эту работу ...)

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

Декер : Это немного помогает. К сожалению, я записываю эту DLL в спецификацию, поэтому на самом деле у меня нет доступа к файлу конфигурации приложения. Как вы заметите выше, мой коллега создал файл «Настройки 1 .settings». Я не понимал этого в то время, но теперь кажется, что добавление «1» не позволяет использовать его в пространстве настроек любого приложения, которое его вызывает.

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

Кроме того, я могу изменить «Тип вывода» моей сборки с «Библиотеки классов» на «Приложение Windows» и добавить следующие строки в начале моего кода DLL:

    [STAThread]
    public static void Main(string[] args)
    {
        System.Windows.Forms.Application.Run(new form());
    }

Когда я запускаю этот файл, он генерирует другой файл конфигурации («.exe.config»), который я могу изменить, и получить из него новые данные. Так что я немного растерялся. Есть идеи?

Ответы [ 9 ]

7 голосов
/ 10 октября 2008

Я использую эту технику все время. Часто у меня есть сборка библиотеки, которая требует определенных настроек, и мне нужно, чтобы они устанавливались как путем тестирования проектов, так и с помощью основных «исполняемых» сборок - будь то веб-проекты или проекты служб Windows.

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

Вот фрагмент, показывающий такой атрибут:

Вот фрагмент, который показывает значение по умолчанию для ConcordanceServicesEndpointName в сгенерированном классе:

    [global::System.Configuration.ApplicationScopedSettingAttribute()]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Configuration.DefaultSettingValueAttribute("InternalTCP")]

    public string ConcordanceServicesEndpointName {
        get {
            return ((string)(this["ConcordanceServicesEndpointName"]));
        }
    }

То, что вы хотите сделать, это скопировать раздел конфигурации из файла app.config из проекта сборки библиотеки и аккуратно объединить его с соответствующим web.config или app.config для основной сборки. Во время выполнения это единственный используемый конфигурационный файл.

Вот пример:

<code><configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="LitigationPortal.Documents.BLL.DocumentsBLLSettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <applicationSettings>
    <LitigationPortal.Documents.BLL.DocumentsBLLSettings>
      <setting name="ConcordanceServicesEndpointName" serializeAs="String">
        <value>InternalTCP</value>
      </setting>
    </KayeScholer.LitigationPortal.Documents.BLL.DocumentsBLLSettings>
  </applicationSettings>

Вам следует скопировать эти разделы в «истинный» файл конфигурации.

2 голосов
/ 12 ноября 2008

У меня была такая же проблема в течение длительного времени - это раздражает.

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

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

Например, у меня есть класс, который использует LINQ-To-SQL для связи с БД. Таким образом, у него есть файл Setting1.settings, в котором хранится строка подключения к базе данных. Вводимое по умолчанию значение (после перетаскивания таблиц базы данных в конструктор) представляет собой строку подключения базы данных dev.

После создания файла DBML на основе тестовой базы данных я могу зайти и отредактировать файл настроек и ввести имя базы данных, например, "FAKE_DATABASE".

Таким образом, если вы используете DLL в другом проекте, а затем забыли объединить файлы конфигурации, чтобы добавить правильное значение конфигурации для DLL, по крайней мере вы получите сообщение об ошибке типа «Не удается подключиться к FAKE_DATABASE». ».

Конечно, если вам снова придется работать с конструктором, вам придется изменить значение обратно на значение вашей базы данных dev.

Огромная боль. Они должны как-то это изменить.

2 голосов
/ 11 октября 2008

Я решаю эту проблему в приложении, которое находится в процессе прототипирования. Хотя предложение Декера о совместном взломе файлов конфигурации должно сработать, я думаю, что это довольно неудобный ручной взлом, выполняемый как часть цикла сборки. Вместо этого я решил, что самое чистое решение - просто заставить каждую библиотеку анализировать свой собственный файл library.dll.config. Он все еще не совершенен и требует некоторого дополнительного кода, но кажется, что это единственный способ обойти византийский способ обработки этих файлов app.config .Net.

1 голос
/ 11 октября 2008

Мне кажется, я только что нашел объяснение того, почему это не работает для моей DLL и моего тестового приложения. Вот заключительное исключение из блога какого-то парня :

Исправление для этого - либо убедиться, что ваше приложение и вспомогательные сборки имеют одинаковое пространство имен, либо объединить содержимое AppName.exe.config и DllName.dll.config (да, когда вы компилируете .dll теперь он генерирует этот файл, однако он игнорируется, если вы копируете его в каталог приложения, и не объединяется автоматически)

Так что либо я должен держать DLL и приложение в одном и том же пространстве имен, либо я должен объединить содержимое файла конфигурации DLL с файлом конфигурации приложения.

(Разве такого рода не побеждать назначение DLL? Я думал, что DLL должна была быть независимой библиотекой.)

Возможно, именно поэтому это работает для моего сотрудника. Производственное приложение использует то же пространство имен, что и DLL. (Мое тестовое приложение явно не ...)

ОБНОВЛЕНИЕ: Я недавно сел со своим коллегой и снова поговорил об этой проблеме, и кажется, что она никогда не работала и для него, но он не понял этого, потому что он задал начальное значение должно быть таким же, как устройство, которое мы пытались использовать. Поэтому, конечно, сначала это работало, но как только мы развернули его в другом месте с немного другими настройками, оно снова сломалось.

1 голос
/ 10 октября 2008

Очевидно ваше приложение пытается прочитать из файла конфигурации по умолчанию (который, вероятно, является файлом конфигурации приложения). Чтобы убедиться, добавьте пару ключ-значение в файле конфигурации dll в файл конфигурации приложения, запустите приложение и посмотрите, читается ли оно на этот раз.

0 голосов
/ 10 марта 2017

Ответ Говарда охватывает теорию.

Одним из быстрых и грязных способов решения этой проблемы является ручной анализ файла конфигурации xml.

    string configFile = Assembly.GetExecutingAssembly().Location + ".config";
    XDocument.Load(configFile).Root.Element("appSettings")....
0 голосов
/ 16 августа 2012

Думаю, вы все допускаете ошибку в том, что вы, по-видимому, ссылаетесь на настройки DLL через Settings1.Default.IPAddress, в то время как вы просто должны сделать это Settings1.IPAddress.

Разница в том, что при использовании Settings1.Default.IPAddress значения получаются из жестко закодированных значений, включенных в файл сборки (.dll или .exe), как атрибут [global :: System.Configuration.DefaultSettingValueAttribute (...)] ,

Хотя Settings1.IPAddress - это значение, которое можно редактировать в файле .dll.config (файл XML) **. поэтому любые изменения, внесенные в файл XML, не отражаются в жестко заданном значении по умолчанию в сборке.

Не это:

IP = IPAddress.Parse(Settings1.Default.IPAddress);

Но попробуйте это:

*IP = IPAddress.Parse(Settings1.IPAddress);
0 голосов
/ 06 января 2009

Возможно, что в вашей DLL у вас есть модификатор доступа (для Settings1.Settings), установленный на Internal (Friend for VB). Попробуйте изменить Access MOdifier на Public и посмотрите, позволяет ли это приложение читать / записывать значения из конфигурации dll.

0 голосов
/ 10 октября 2008

Я видел похожую проблему при использовании app.config. Попробуйте запустить приложение из .exe, а не из Visual Studio, и посмотрите, будет ли оно работать должным образом.

...