假设C#中有一个简单的类:
[Serializable]
public class MyClass
{
public int A { get; set; }
public int B { get; set; }
[XmlIgnore]
public int Sum { get; }
}
这是从包含A和B值的简单XML文件反序列化的。但是,Sum
是使用A
和B
计算的,未经序列化。假设我不想在访问器中动态计算Sum。如何预先计算Sum
?首先调用构造函数,当然,这意味着A和B稍后不作为符号,因此还没有用来计算Sum。是否有某种后反序列化或后期实例 thingie 我可以使用这样的对象完全一步创建?我只是不希望我的对象永远处于不完整和无效的状态。
答案 0 :(得分:5)
我想你正试图问别的。这个用例并不能证明您要求的解决方案的复杂性。
如果是用例:
e.g。
if (_alreadyCalculated)
{
return _sum;
}
_sum = A+B;
_alreadyCalculated = true;
return _sum;
答案 1 :(得分:3)
我认为您正在寻找OnDeserializedAttribute标记在反序列化对象后需要调用的方法
编辑 - 错过了XmlSerializer
部分....
你最好的选择是在A和B的setter方法中重新计算总和
或者,您可以使用Sum {get}使用Lazy
答案 2 :(得分:2)
您应该使用常规属性并在Sum
和A
的设置器中重新计算B
。
答案 3 :(得分:2)
您可以采用的一种方法是自行修改序列化程序。您可以使用SGen获取序列化程序的代码,如下所示:
sgen /f /k /a:MyAssembly.dll
这会将XmlSerializer'temp'文件保留在当前目录中。将该代码添加到项目中并进行更改。
global::ConsoleApplication31.Foo Read2_Foo(bool isNullable, bool checkType) {
// ...
if (Reader.IsEmptyElement) {
Reader.Skip();
return Callback(o);
}
// ...
return Callback(o);
}
private T Callback<T>(T value) {
if (value is IDeserializationCallback)
((IDeserializationCallback)value).OnDeserialization(this);
return value;
}
然后,您可以直接在代码中实例化序列化程序。您可以使用NRefactory(查找Read_*
方法并更改任何返回行)来自动执行此操作 - 如果不这样做,则会产生维护开销。样品用法:
var ser = new FooSerializer();
using (var sr = new StringReader("<foo />"))
{
var foo = ser.Deserialize(sr);
}
Console.ReadLine();