【问题标题】:Where to initialize Properties.Settings objects with Application scoop?在哪里使用 Application scoop 初始化 Properties.Settings 对象?
【发布时间】:2014-02-04 00:13:27
【问题描述】:

我使用Properties > Settings 对话框将Settings.settings 文件添加到我的项目中。我创建了一个新的配置元素,其类型为自定义类型。自动生成的代码输出如下:

[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::Moslem.Model.Configuration.ApplicationConfiguration AppConfig
{
    get 
    {
        return ((global::Moslem.Model.Configuration.ApplicationConfiguration)(this["AppConfig"]));
    }
}

到目前为止,这很好。默认情况下,所有带有ApplicationScopedSettingAttribute 的设置都是只读的。因此,我不能简单地在应用程序的其他地方启动它。显然,对ApplicationConfiguration 对象的任何属性的任何使用都会抛出NullReferenceException

我的问题:

  1. 是否有标准方法来启动所有具有应用程序范围的对象?
  2. 简单地编写自己的构造函数并启动对象是否安全? (因为Properties.Settings 是自动生成的部分)

【问题讨论】:

  • 它们是从您的 .config 文件的内容初始化的。给他们一个默认值往往是陷入成功陷阱的好方法。
  • @HansPassant:你能写一个例子吗?我正在尝试在 MVC 应用程序的 Application_Start() 中分配一些值。我不确定 .config 文件当时是否存在。

标签: c# properties settings nullreferenceexception


【解决方案1】:

我不知道您第二个问题的答案,但这是我从数据库查询中初始化设置值的方式。我认为这将与运行时通常期望的生命周期相匹配。

首先,为您的自动生成的设置类创建一个匹配的部分类实现:

[SettingsProvider(typeof(CustomSettingsProvider))]
internal sealed partial class Settings : ApplicationSettingsBase 
{
    public Settings()
    {
        CustomSettingsProvider.UpdateCustomSettings += delegate(object sender, EventArgs e)
        {
            this.Reload();
        };
    }
}

SettingsProvider 属性标识作为设置来源的类。

事件处理程序是可选的。如果值异步更改,这是一种强制设置在运行时重新加载的方法。

SettingsProvider 如下所示:

public partial class CustomSettingsProvider : System.Configuration.SettingsProvider, System.Configuration.IApplicationSettingsProvider
{
    // raise this event to cause the settings to be reloaded at runtime after initialization
    public static event EventHandler UpdateCustomSettings;

    public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
    {
        SettingsPropertyValueCollection result = new SettingsPropertyValueCollection();

        // the collection identifies properties to initialize
        foreach (SettingsProperty property in collection)
        {
            SettingsPropertyValue spv = new SettingsPropertyValue(property);

            // determine value...

            spv.PropertyValue = value;
            result.Add(spv);
        }

        return result;
    }
}

基类中有一些可重写的方法,但大部分工作都在 GetPropertyValues 方法中完成。集合参数标识需要初始化的属性,为每个属性查找值,或提供一些默认值以避免您的 NullReferenceExceptions。

我们正在使用这种技术进行授权设置。我们在应用程序中有几个模块,每个模块都有一组不同的授权设置,但都绑定到同一个 CustomSettingsProvider。

读取设置的数据库代码与 CustomSettingsProvider 类是分开的,但 CustomSettingsProvider.GetPropertyValues 方法可以通过单例接口访问。我们在 CustomSettingsProvider 上添加了一个公共静态方法来引发 UpdateCustomSettings 事件(由于事件和方法都是静态的,因此没有事件“发送者”,但无论如何也不使用事件参数)。

当数据库查询完成并读入设置时,会在 CustomSettingsProvider 类上调用静态方法,这会引发 UpdateCustomSettings 事件,然后 Settings 类会调用它的 Reload 方法。默认的 Reload 实现调用 GetPropertyValues 方法以使用数据库中的新数据重新初始化所有设置值。

【讨论】:

  • 是的,我错过了代表的论点(见编辑)。或者您可以使用 lambda 表达式:CustomSettingsProvider.UpdateCustomSettings += (sender, e) => this.Reload();
  • 感谢 Doug 似乎成功了。您对从数据库加载设置有任何指示吗?我的要求是用运行时从 sql 加载的设置替换现有设置
  • 在上面答案的末尾添加了使用场景(评论太长了)。
【解决方案2】:

我找到了在应用程序启动时启动它的最快方法,但是需要从数据库中重新加载值。我创建了一个带有部分类定义的新文件。我所要做的就是初始化属性隐藏字段:

namespace Application.Web.Properties
{
    public sealed partial class Settings
    {
        Settings()
        {
            this["AppConfig"] = new ApplicationConfiguration();
        }
    }
}

当我尝试以下操作时,我不再得到 NullReferenceException

Properties.Settings.Default.AppConfig.PageTitle = "My Application";
Properties.Settings.Default.AppConfig.Description = "Cool Application 2014";
Properties.Settings.Default.AppConfig.Author = "Moslem © 2014";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2014-04-27
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    相关资源
    最近更新 更多