Settings.Default. & Lt; property > всегда возвращает значение по умолчанию вместо значения в постоянном хранилище (файл XML)

StackOverflow https://stackoverflow.com/questions/192641

Вопрос

Недавно я написал 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);
        }
    }

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

  

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

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

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

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

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

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

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

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

    Это было полезно?

    Решение

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

    Другие советы

    Я использую эту технику все время. Часто у меня есть сборка библиотеки, которая требует определенных настроек, и мне нужно, чтобы они устанавливались как путем тестирования проектов, так и с помощью основного " исполняемого файла " сборки - будь то веб-проекты или проекты служб 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 для основной сборки. Во время выполнения это единственный используемый конфигурационный файл.

    Вот пример:

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

    Вы должны скопировать эти разделы в " true " Конфигурационный файл.

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

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

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

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

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

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

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

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

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

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

      

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

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

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

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

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

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

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

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

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

        string configFile = Assembly.GetExecutingAssembly().Location + ".config";
        XDocument.Load(configFile).Root.Element("appSettings")....
    

    Ошибка, которую я думаю, вы все делаете, заключается в том, что вы явно ссылаетесь на настройки 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);
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top