在.NET应用程序开发中,管理用户和应用程序的设置是一项常见需求。默认情况下,.NET提供了一个集成的机制来存储这些设置,使得开发者可以轻松地创建和使用它们。然而,在某些情况下,例如开发便携式应用程序时,开发者可能需要将设置存储在应用程序文件夹中,而不是用户的AppData目录。本文将介绍如何通过实现自定义设置提供程序来实现这一需求。
.NET框架为Windows Forms或WPF应用程序提供了一个存储应用程序和用户设置的机制。这些设置通常分为两类:用户范围的设置,每个用户账户都有一份,并且可以读写;应用程序范围的设置,通常是只读的。这些设置通过从ApplicationSettingsBase派生的设置类来访问,该类提供了设置属性和加载/保存的基本方法。
但是,实际的数据是由从SettingsProvider派生的类提供的,这个类负责加载和存储数据。默认的设置提供程序将用户范围的设置以XML格式存储在用户AppData目录下的user.config文件中。对于大多数应用程序来说,这是足够的,但在某些情况下,例如便携式应用程序,可能需要一个替代的存储位置。由于默认设置提供程序的存储位置无法更改,因此必须实现自己的设置提供程序。这并不复杂,只需要实现几个方法。然而,有一些细节需要注意。
在Visual Studio中,可以通过设置设计器将便携式设置提供程序应用到应用程序设置中。为此,请转到设置设计器,选择一个设置并打开其属性页面。它包含一个默认为空的Provider字段,将其设置为提供程序的名称。请注意,必须指定包括命名空间在内的类的完整名称,例如Bluegrams.Application.PortableSettingsProvider。
值得注意的是,设置提供程序必须为每个设置属性单独设置。这允许灵活性,但可能不是最简单的方法,特别是对于大型设置文件。
因此,这种便携式设置提供程序的实现提供了一种更简单的方法。要使设置类中的所有设置都可移植,只需使用其ApplyProvider()方法,如下所示:
C#
PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
当应用时,便携式设置提供程序将用户范围的设置存储在应用程序文件夹中名为portable.config的文件中。如果该文件不存在,则使用默认值并创建一个新文件。数据以类似于默认设置文件的XML样式格式进行序列化。
应用便携式设置提供程序后,用户范围的设置存储在应用程序文件夹中的portable.config文件中。如果该文件不存在,则使用默认值并创建一个新文件。数据以类似于默认设置文件的XML样式格式进行序列化:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<Roaming>
<Bluegrams.Application.WPF.Properties.Settings>
<Culture></Culture>
</Bluegrams.Application.WPF.Properties.Settings>
<TestWpfApp.Properties.Settings>
<RoamedSetting>Default text</RoamedSetting>
</TestWpfApp.Properties.Settings>
</Roaming>
<PC_MachineName>
<Bluegrams.Application.WPF.Properties.Settings>
<Width>640</Width>
<Height>480</Height>
<Left>100</Left>
<Top>100</Top>
</Bluegrams.Application.WPF.Properties.Settings>
<TestWpfApp.Properties.Settings>
<LocalSetting>Default text</LocalSetting>
</TestWpfApp.Properties.Settings>
</PC_MachineName>
</userSettings>
</configuration>
有几个值得注意的点。首先,文件被分为一个Roaming部分和一个以当前PC名称命名的部分。Roaming部分中的属性是可以移植到另一台机器的,而所有其他设置都是特定于一台机器的(例如窗口位置或大小的设置应该在这里找到)。要将设置放置在Roaming部分,只需为该设置设置Roaming属性为true。
然后,设置属性进一步被划分为它们所属的设置类。这允许来自不同位置的不同类共享同一个设置文件。
自定义设置提供程序只需要实现三个方法,其中GetPropertyValues()和SetPropertyValues()是两个重要的方法。这些方法接收一组设置属性,并执行XML文件的加载或保存。由于提供程序应该只处理用户范围的设置,并且必须区分漫游和非漫游设置,方法IsRoaming()和IsUserScoped()遍历属性的属性来检查这一点。IsRoaming()方法搜索SettingsManageabilityAttribute,而IsUserScoped()方法指示是否存在UserScopedSettingAttribute。
作为第三个方法,必须从基类覆盖Initialize()。在这里,重要的是指定name参数的值,因为这个参数不能留空。
接下来,确保Reload()方法按预期工作。为了实现这一点,设置提供程序不会在其自身上缓存任何已加载的XML内容,而是每次调用GetPropertyValues()方法时从文件加载设置。这听起来极其低效,但设置类本身会缓存属性,因此设置提供程序只有在设置确实需要重新加载时才会起作用,例如,调用了Reload()方法。