是否可以将不可变类型用作.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,因为它会抛出此异常:
System.Configuration.ConfigurationErrorsException:属性“criterion”的值无法转换为字符串。错误是:无法找到支持转换为/来自字符串的转换器,用于“FindCriterion”类型的属性“标准”。
如果我从ConfigurationElement派生出ImmutableClass,当我尝试序列化和反序列化配置部分时会出现此异常:
System.Reflection.TargetInvocationException:调用目标抛出了异常。 ---> System.Reflection.TargetInvocationException:调用目标抛出了异常。 ---> System.MissingMethodException:没有为此对象定义无参数构造函数。
我可以完全控制ImmutableClass,因此我可以实现所需的任何接口。
有什么办法可以挂钩配置API,以便可以这种方式使用ImmutableClass吗?
答案 0 :(得分:4)
就我个人而言,我认为您最好将配置部分中的数据(看似需要变量)分开,以及如何在对象模型中表示它。没有什么可以阻止你有两个表示 - 一个简单的(DTO / POCO)版本的配置,你的自定义版本(在这种情况下是不可变的)在你的应用程序中实际使用。
答案 1 :(得分:1)
您可以使用一些TypeConverters来帮助完成此过程(链接到System.Configurations.ConfigurationConverter)。
真正的问题是你为什么要给自己造成这么多麻烦?有时候,最好放下并接受它而不是打架。如果您尝试以除了针对您的特定方式之外的任何方式执行此操作,框架的某些部分会令人沮丧....
答案 2 :(得分:0)
我会放弃那个诅咒,因为这个想法被诅咒失败了。所有配置节处理程序必须具有默认(无参数)构造函数。您的不可变对象不是这种情况。
最简单的解决方案是在配置和应用程序之间添加另一个抽象级别。您可以应用配置提供程序模式,并将配置节的“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);
}
}
}
我就是这样做的,到目前为止它已经为我服务了。
希望它有所帮助。