在.NET应用程序中,如果您有特定的设置需求,例如将它们存储在数据库中,那么您可以替换LocalFileSettingsProvider为您的示例的自定义设置提供程序:
要声明ApplicationSettingsBase要使用特定提供程序的设置类(继承的类),请使用它来装饰它SettingsProviderAttribute并将提供程序类型作为参数传递[SettingsProvider(typeof(MyCustomProvider))],否则它将使用默认值LocalFileSettingsProvider.
我的问题:是否有一个配置或技巧可以强制我的应用程序在不使用属性的情况下在整个应用程序中使用我的自定义提供程序?
原因是我通过MEF加载插件,插件可能是通过第三方编写的,我不希望他们关心如何处理设置.
在这个问题之后,我在我们正在开发的旧版C#应用程序中成功创建了自定义设置提供程序.它通过SettingsProvider属性引用:
public sealed class MySettings : SettingsProvider
{
...
}
[SettingsProvider(typeof(MySettings))]
internal sealed partial class Settings {}
Run Code Online (Sandbox Code Playgroud)
但是,现在我遇到了另一个问题.
我们的客户端应用程序包含一个autoupdate工具,它的实现使得大部分客户端 - 包括上面的类 - 都构建在一个DLL中(我们在这里称之为client.dll),然后由EXE使用.如果需要,EXE首先检查更新并从更新服务器下载最新的更新,用其较新版本(包括client.dll)替换所有DLL等.为了能够在运行时替换DLL,它无法静态链接到它们.所以在更新之后,它加载client.dll并像这样运行它:
Assembly assy = Assembly.LoadFile(
AppDomain.CurrentDomain.BaseDirectory + "client.dll");
object frm = assy.CreateInstance("Client.Forms.MainForm");
Application.Run((Form)frm);
Run Code Online (Sandbox Code Playgroud)
这样做的不幸结果是框架无法在动态加载的程序集中找到我的自定义设置提供程序类.我尝试使用LoadFrom而不是LoadFile上面但它没有帮助.到目前为止,我发现的唯一可行的解决方案是在loader exe中实现一个与真实设置提供程序同名的代理类,框架可以找到它.然后,代理从客户端程序集中实例化实际设置提供程序,并委派对它的所有调用.
这似乎有效但我不满意.有没有办法帮助框架直接在动态加载的程序集中查找我的类?
我收到的错误消息:
System.Configuration.ConfigurationErrorsException: Failed to load provider type: Client.Properties.MySettings, Client, Version=4.0.1341.0, Culture=neutral, PublicKeyToken=null.
at System.Configuration.ApplicationSettingsBase.get_Initializer()
at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propInfo)
at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
at System.Configuration.ApplicationSettingsBase.get_Properties()
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName) …Run Code Online (Sandbox Code Playgroud) 在实现自定义设置提供程序时,我注意到访问设置属性的值会将其IsDirty标志更改为true.
// Arrange
var property = new SettingsProperty("property1")
{
PropertyType = typeof(Color),
DefaultValue = "Green"
};
// Act
var result = new SettingsPropertyValue(property);
// Assert
Assert.That(result.IsDirty, Is.False);
Assert.That(result.PropertyValue, Is.EqualTo(Color.Green));
Assert.That(result.IsDirty, Is.False); // <-- Assertion fails
Run Code Online (Sandbox Code Playgroud)
Reflector给出了一个问题的答案,为什么PropertyValuegetter的行为是这样的 - 它包含如下语句:
if (_Value != null && !Property.PropertyType.IsPrimitive && !(_Value is string) && !(_Value is DateTime))
{
_UsingDefaultValue = false;
_ChangedSinceLastSerialized = true;
_IsDirty = true;
}
Run Code Online (Sandbox Code Playgroud)
乍一看奇怪的行为可以让任何人对此有所了解吗?
当前,我的应用程序的用户设置存储在此默认目录中:
C:\Users\{User Name}\AppData\Roaming\{Company Name}\{Assembly Name}.vshos_Url_{Hash}\{Assembly Version}
Run Code Online (Sandbox Code Playgroud)
我知道默认Microsoft命名规则的含义,我的问题是:如何在执行时更改defaut文件夹或通过修改appconfig文件?
我的意图是只能处理将应用程序的用户设置保存到的目录,例如,我想将用户设置文件保存在以下目录中:
C:\Users\{User Name}\AppData\Roaming\{Assembly Name}
Run Code Online (Sandbox Code Playgroud)
我知道这是可以实现的,因为我已经看到很多.NET应用程序可以将其userconfig文件存储在自定义漫游文件夹中,该文件夹不遵循Microsoft默认规则以及未处理的哈希和其他令人讨厌的命名规则。