想象一下,我需要一个调色板来使Winforms应用程序具有一致的外观。

我所做的是创建了一个静态的helper类和可以在代码中任何地方调用的helper方法,然后调用什么我需要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);
        }
    }
}


选择这种类型的体系结构是否犯了明显的错误?

#1 楼

虽然与您的问题有些切线,但是您可能仍然会发现它很有帮助。我发现使用自定义配置部分比必须记住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>


最后,您可以通过以下方式使用配置:

一些注意事项:


由于默认情况下VS中通常不引用System.Configuration程序集,因此您需要引用它。 ConfigurationManager.GetSection("uboldi")在app.config文件中需要该节的名称。您会注意到,这在上面的示例中是匹配的。
app.config文件中的section元素使用标准的.Net类型名称约定来定位指定的配置部分。在此示例中,我假设UboldiConfigurationSection类型是Uboldi命名空间,并且位于Uboldi程序集(dll或exe)中。
您可以通过创建ConfigurationElement子类并将它们用作配置节和元素中的属性来添加层次结构。
上面的链接用于Web.config,但是在app.config文件中也可以实现同样的目的。


#2 楼

我认为可以。另一个选择是为表单创建第二个构造函数,然后在以下标题中传递标题: />您还可以将硬编码的表单标题进一步提取到配置文件或资源文件中,然后像这样实例化表单:

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

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


这样做的收益取决于将来有多大可能会改变,或者您是否打算将应用程序翻译成其他语言。

#3 楼

CustomizationHelper的目的仅仅是为了提取ConfigurationManager / AppConfig内容吗?因为否则我只会坚持直接使用ConfigurationManager调用。

了解发生了什么事情所需的功夫越少,我的书越好。除非有一天有必要从另一个来源(例如数据库)获取SchoolName。属性或“ GetName()”方法。

#4 楼

就我个人而言,我将使它们成为静态属性,而不是静态方法。用C#看起来更自然。但是,使用静态帮助程序类来检索配置值的概念很合理。当您检索非字符串类型时,它会变得更加有用,因为您可以将转换内容抽象到帮助程序类中。配置值实际上在那里吗?

#5 楼

呈现的代码似乎还可以,没有任何明显的问题。 CustomizationHelper可能会使用更好的名称来表示正在定制的内容。如果这是一个较大项目的一部分,则添加注释以表明应该使用CustomizationHelper的类是一个好主意。

#6 楼

一些想法:


名称“ CustomizationHelper”不是很具体。 CustomerBrandingService怎么样?即使它“只是”从配置文件中获取数据,但情况并非总是如此,它仍然是应用程序服务。 (使用“ Helper”命名类类似于使用“ Manager”命名-请参见下面的参考。)

此外,尽管您的问题合理而简单,但我不清楚您会做出哪些决定将从中获得收益。例如,如果这是整个应用程序的基础,我建议您考虑其他一些选择:


为什么要在2011年构建WinForm应用程序?请考虑使用WPF或Silverlight(可能是Silverlight浏览器外的“ SLOOB”)。
如果选择WPF或Silverlight,则将通过Model-View-ViewModel模式使用数据绑定来最自然地分配标题。 >
指针以获取更多信息:


如何避免将每个类都称为“ Manager”类
使用WPF进行数据绑定(Silverlight非常相似)
WPF和Silverlight的模型-视图-视图模型设计模式


#7 楼

我第二个配置部分。优点是可以根据需要设置设置,在GetSection调用时引发异常,而不是通过AppSettings [nonexistingKey]传递空值

#8 楼

我认为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);
}