自动后反序列化执行

时间:2011-09-12 23:45:43

标签: c# deserialization xml-deserialization

假设C#中有一个简单的类:

[Serializable]
public class MyClass
{
    public int A { get; set; }
    public int B { get; set; }
    [XmlIgnore]
    public int Sum { get; }
}

这是从包含A和B值的简单XML文件反序列化的。但是,Sum是使用AB计算的,未经序列化。假设我不想在访问器中动态计算Sum。如何预先计算Sum?首先调用构造函数,当然,这意味着A和B稍后不作为符号,因此还没有用来计算Sum。是否有某种后反序列化或后期实例 thingie 我可以使用这样的对象完全一步创建?我只是不希望我的对象永远处于不完整和无效的状态。

4 个答案:

答案 0 :(得分:5)

我想你正试图问别的。这个用例并不能证明您要求的解决方案的复杂性。

如果是用例:

  1. 动态计算。把Sum变成一种方法。
  2. 如果您担心开销,请使用支持字段。
  3. 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)

您应该使用常规属性并在SumA的设置器中重新计算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();