不可变类型作为配置属性

是否可以将不可变类型用作.NET配置API的配置属性?

假设我有一个名为MyClass的不可变类型:

public class ImmutableClass { private readonly int value; public ImmutableClass(int value) { this.value = value; } public int Value { get { return this.value; } } } 

我想在ConfigurationSection中使用此类型作为配置属性:

 public class MyConfigurationSection : ConfigurationSection { [ConfigurationProperty("foo")] public ImmutableClass Foo { get { return (ImmutableClass)base["foo"]; } set { base["foo"] = value; } } } 

当我这样做时,我无法序列化和反序列化MyConfigurationSection,因为它会抛出此exception:

System.Configuration.ConfigurationErrorsException:属性“criterion”的值无法转换为字符串。 错误是:无法找到支持转换为/来自字符串的转换器,用于“FindCriterion”类型的属性“标准”。

如果我从ConfigurationElement派生ImmutableClass,当我尝试序列化和反序列化配置部分时,我得到此exception:

System.Reflection.TargetInvocationException:调用目标抛出了exception。 —> System.Reflection.TargetInvocationException:调用目标抛出了exception。 —> System.MissingMethodException:没有为此对象定义的无参数构造函数。

我完全控制ImmutableClass,所以我可以实现任何需要的接口。

有什么方法可以挂钩到配置API,以便可以这种方式使用ImmutableClass?

您可以使用一些TypeConverters来帮助进程(链接到System.Configurations.ConfigurationConverter)。

真正的问题是你为什么要给自己带来这么多麻烦? 有时候,最好放下并接受它而不是打架。 如果您尝试以任何方式执行此框架的某些部分,除了针对您的特定方式之外,该框架的某些部分是令人沮丧的….

就个人而言,我认为你最好将配置部分中的数据(看似需要变量)分开,以及如何在对象模型中表示它。 没有什么可以阻止你有两个表示 – 一个简单的(DTO / POCO)版本的配置,和你的自定义版本(在这种情况下是不可变的)在你的应用程序中的实际使用。

我会放弃那个诅咒,因为这个想法被诅咒失败了。 所有配置节处理程序必须具有默认(无参数)构造函数。 您的不可变对象不是这种情况。

最简单的解决方案是在配置和应用程序之间放置另一个抽象级别。 您可以应用配置提供程序模式,并将配置节的“free for all”可变类转换为可由应用程序使用的不可变类。

我必须说这是应该如何使用配置部分。 我知道有一个可靠的选项,但我以前从未使用过它。

代码可能如下所示:

配置处理程序

 public class SectionHandler : ConfigurationSection { [ConfigurationProperty("foo")] public MyObject ConfigurationValue { get { return (MyObject) this["foo"]; } } } 

从XML文件和对象中获取配置值后,使用配置提供程序模式来使用应用程序中的配置。

配置提供程序看起来像这样:

 public MyConfigurationProvider : IMyconfigurationProvider { public MyImmutabble ConfigurationValue { get { var configurationvalue = (MyObject) ConfigurationManager.GetSection("mySection"); return new MyImmutable(configurationvalue.ConfigurationValue); } } } 

这就是我这样做的方式,到目前为止它一直在为我服务。

希望能帮助到你。