Получение /установка значений по умолчанию из моего App.config

Представьте, что мне нужна цветовая палитра для моего приложения Winforms, чтобы он выглядел последовательно.

Что я сделал, это создать статический вспомогательный класс и вспомогательные методы, которые я могу вызвать из любого места в моем коде, и вызывать то, что мне нужно, из файла App.settings.

Здесь, например, я получаю название школы из файла App.config, поэтому я могу продать это приложение в другие школы с минимальными изменениями с моей стороны.

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="schoolName" value="Uboldi"/>
  </appSettings>
</configuration>
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace Uboldi.Helpers
{
    public static class CustomizationHelper
    {
        public static string GetSchoolName()
        {
            return ConfigurationManager.AppSettings["schoolName"];
        }
    }
}

Использование:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Uboldi.Helpers;

namespace Uboldi
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            LoadFormTitle();
        }

        private void LoadFormTitle()
        {
            var schoolName = CustomizationHelper.GetSchoolName();
            this.Text = String.Format("Sistema {0} - Pagina Principal", schoolName);
        }
    }
}

Есть ли какие-то вопиющие ошибки, которые я делаю, выбирая этот тип архитектуры?

67 голосов | спросил Sergio Tapia 25 Jam1000000amTue, 25 Jan 2011 00:58:21 +030011 2011, 00:58:21

8 ответов


41

Хотя это несколько касательно вашего вопроса, но, тем не менее, вы можете найти его полезным.

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

Используя настраиваемый раздел конфигурации, вы можете создать такой тип конфигурации, как:

public class UboldiConfigurationSection : System.Configuration.ConfigurationSection {
    [ConfigurationProperty("schoolName")]
    public string SchoolName {
        get { return (string)this["schoolName"]; }
        set { this["schoolName"] = value; }
    }
}

Затем для загрузки этого типа конфигурации:

public static class UboldiApplication {
    public static UboldiConfigurationSection Config { get; internal set; }

    public static void Initialize() {
        Config = ConfigurationManager.GetSection("uboldi") as UboldiConfigurationSection;
    }
}

Тогда app.config будет выглядеть примерно так:

<configuration>
    <configSections>
        <section name="uboldi" type="Uboldi.UboldiConfigurationSection, Uboldi" />
    </configSections>
    <uboldi schoolName="Fillmore Central" />
</configuration>

Наконец, вы используете конфигурацию:

public void Test() {    
    //This only needs to be done once, presumably in your Program.Main method
    UboldiApplication.Initialize();

    var name = UboldiApplication.Config.SchoolName;
}

Несколько примечаний:

  1. Вам нужно будет ссылаться на сборку System.Configuration, поскольку она обычно не упоминается в VS по умолчанию.
  2. ConfigurationManager.GetSection("uboldi") ожидает имя раздела в файле app.config. Вы заметите, что это соответствует приведенному выше примеру.
  3. Элемент раздела в файле app.config использует стандартное соглашение об имени типа .Net, чтобы найти указанный раздел конфигурации. В этом примере я предполагаю, что тип UboldiConfigurationSection - это пространство имен Uboldi и сборка Uboldi (dll или exe).
  4. Вы можете добавить иерархию, создав подкласс ConfigurationElement и используя их как свойства в разделе конфигурации и элементах.
  5. Ссылка выше для Web.config, но то же самое можно сделать в файле app.config.
ответил akmad 27 Jam1000000amThu, 27 Jan 2011 01:46:13 +030011 2011, 01:46:13
9

Думаю, все будет хорошо. Другим вариантом было бы создать второй конструктор для формы и передать заголовок в:

public class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
    }

    public MainForm(string schoolName) : this()
    {
        this.Text = String.Format("Sistema {0} - Pagina Principal", schoolName);
    }
}

Это может быть только личное предпочтение.

Вы также можете дополнительно извлечь заголовок жесткой формы в файл конфигурации или ресурса и создать экземпляр формы следующим образом:

var titleFormat = ...; // retrieve format from some place
var schoolName = CustomizationHelper.GetSchoolName();
var form = new MainForm() { Text = string.Format(titleFormat, schoolName) };

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

ответил Adam Lear 25 Jam1000000amTue, 25 Jan 2011 03:26:28 +030011 2011, 03:26:28
8

Является ли цель CustomizationHelper просто абстрагированием материала ConfigurationManager /AppConfig? Потому что иначе я бы просто придерживался прямого вызова ConfigurationManager.

Чем меньше обручей требуется, чтобы понять, что происходит, тем лучше в моей книге. Если вы не увидите необходимость когда-нибудь получить SchoolName из другого источника (например, сказать базу данных).

В любом случае имя класса, вероятно, может быть улучшено, возможно, что-то вроде «SchoolConfiguration» и имеет свойство «Name» или «GetName ()».

ответил mletterle 25 Jam1000000amTue, 25 Jan 2011 04:12:56 +030011 2011, 04:12:56
3

Лично я бы сделал их статическими свойствами, а не статическими. Просто кажется более естественным с C #. Но концепция статического вспомогательного класса для получения значений конфигурации является звуковой. Это становится еще более полезным, когда вы извлекаете нестроковые типы, так как вы можете абстрагировать отбрасывание класса-помощника.

Только один комментарий - как насчет некоторой обработки ошибок в классе-помощнике, чтобы убедиться, что значения конфигурации на самом деле там?

ответил Dan Diplo 27 Jam1000000amThu, 27 Jan 2011 01:19:12 +030011 2011, 01:19:12
2

Представленный код выглядит хорошо, с ним нет никаких очевидных проблем. CustomizationHelper может, вероятно, использовать лучшее имя, хотя для указания того, что настраивается. Если это часть более крупного проекта, было бы полезно поставить комментарий, чтобы указать, какие классы предполагают использовать CustomizationHelper.

ответил greatwolf 25 Jam1000000amTue, 25 Jan 2011 02:46:12 +030011 2011, 02:46:12
2

Несколько мыслей:

  • Название «CustomizationHelper» не очень специфично. Как насчет CustomerBrandingService? Несмотря на то, что он «просто» извлекает данные из конфигурационного файла, это может быть не всегда так, и оно по-прежнему является службой приложений. (Классы именования с «Помощником» похожи на имена с «Менеджером» - см. Ссылку ниже.)

Кроме того, хотя ваш вопрос разумный и простой, мне непонятно, какие решения вы сделаете из этого. Например, если это является основой для целого приложения, я предлагаю другие варианты:

  • Почему вы создаете приложение WinForm в 2011 году? Рассмотрим WPF или Silverlight (возможно, Silverlight Out-of-Browser «SLOOB»).

  • Если вы выберете WPF или Silverlight, заголовок будет назначаться наиболее естественно, используя привязку данных через шаблон Model-View-ViewModel.

Указатели для получения дополнительной информации:

ответил codingoutloud 27 Jam1000000amThu, 27 Jan 2011 02:40:07 +030011 2011, 02:40:07
1

Я второй раздел конфигурации. Это имеет преимущество, чтобы установить параметр по мере необходимости, вызывая исключение в вызове GetSection, вместо передачи нулевого значения с помощью AppSettings [nonexistingKey]

ответил 27 Jam1000000amThu, 27 Jan 2011 01:59:46 +030011 2011, 01:59:46
1

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

public static class AppSettingsHelper
{
    private static TReturnType LoadAppSetting<TReturnType>(string name, bool required, TReturnType defaultValue)
    {
        // Check for missing settings
        if (!ArrayExt.Contains<string>(ConfigurationManager.AppSettings.AllKeys, name))
        {
            if (required)
                throw new ConfigurationErrorsException(string.Format("Required setting missing: {0}", name));
            else
                return defaultValue;
        }

        // Read the setting and return it
        AppSettingsReader reader = new AppSettingsReader();
        return (TReturnType)reader.GetValue(name, typeof(TReturnType));
    }

    //example boolean property
    public static bool IsSomethingSet
    {
        get
        {
            return ApplicationSettingsHelper.LoadAppSetting<bool>(
                "settingName",
                true,
                false);
        }
    }

    //int property
    public static int SomeCount
    {
        get
        {
            return ApplicationSettingsHelper.LoadAppSetting<int>(
                "someCount",
                true,
                0);
        }
    }
}

Используйте это:

if (AppSettingsHelper.IsSomethingSet)
{
    Console.WriteLine(AppSettingsHelper.SomeCount);
}
ответил 28 Jpm1000000pmFri, 28 Jan 2011 20:15:12 +030011 2011, 20:15:12

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132