考虑这个接口和类…
public interface IValueHolder{}
public class ValueHolder<TValue> : IValueHolder {
public ValueHolder(TValue value) => this.value = value;
public TValue value { get; }
public static implicit operator ValueHolder<TValue>(TValue value) => new ValueHolder<TValue>(value);
public static implicit operator TValue(ValueHolder<TValue> valueHolder) => valueHolder.value;
}
class ValueStorage : Dictionary<string, IValueHolder>{}
请注意与之间的隐式转换
TValue
.
这段代码的要点是,我试图存储键/值对,其中的值可以是任何类型,但没有装箱惩罚。这是可能的,因为在设置或从存储器中检索值时,我总是知道类型。(这就是为什么我没有使用
Dictionary<string, object>
.)
现在考虑这个代码…
var storage = new ValueStorage();
storage["UltimateQuestion"] = new ValueHolder<string>("What do you get when you multiply six by nine?");
storage["UltimateAnswer"] = new ValueHolder<int>(42);
var jsonSerializerSettings = new JsonSerializerSettings{
TypeNameHandling = TypeNameHandling.None,
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};
var jsonString = JsonConvert.SerializeObject(storage, jsonSerializerSettings);
结果是。。。
{
"UltimateQuestion": {
"value": "What do you get when you multiply six by nine?"
},
"UltimateAnswer": {
"value": 42
}
}
我希望通过这种含蓄的转换
TValue
,它们是
string
和
int
分别地,它会给我这个。。。
{
"UltimateQuestion": "What do you get when you multiply six by nine?",
"UltimateAnswer": 42
}
那我该怎么办
ValueStorage<T>
序列化和反序列化为
T
? 我不介意编写自定义转换器(前提是它们是通用的,并且可以基于
TValue
)还是习俗
SettingsContractResolver
子类,但我不确定从哪里开始。
使现代化
我越想这个问题,就越觉得这个问题实际上无法解决。这是因为虽然序列化很容易,但反序列化需要知道
TValue
,而不是以我想要的格式存储在JSON中,因此
不能
被反序列化。(即使是上面带有嵌套对象的原始输出也有同样的问题。您需要类型信息才能在任何容量下工作。)
然而,为了不让这个问题一直悬而未决,那么一个为其存储类型信息的转换器呢
TValue
而不是
ValueHolder<TValue>
?
例如
{
"UltimateQuestion": {
"$type": "[Whatever TValue is--string here]",
"value": "What do you get when you multiply six by nine?"
},
"UltimateAnswer": {
"$type": "[Whatever TValue is--int here]",
"value": 42
}
}
这样转换器就可以重建
估价师<TValue>
反序列化期间的实例。它并不完美,但至少可以在不暴露ValueHolder框架的情况下进行适当的反序列化。