找出是否在DeSerialization过程中调用属性设置器

Hor*_*ter 9 c# deserialization c#-4.0

有没有办法找出对象属性是否作为DeSerialization过程的一部分被调用(例如,由XmlSerializationReaderXXX).

背景:典型情况是在这种情况下禁用事件和复杂操作,直到初始化完成.

我发现的一种方法是"解释"堆栈并查看是否触发了呼叫 XmlSerializationReaderXXX,这不是那么优雅恕我直言.有更好的吗?

public SomeClass SomeProperty
    {
        get { ..... }
        set
        {
            this._somePropertyValue = value;
            this.DoSomeMoreStuff(); // Do not do this during DeSerialization
        }
    }
Run Code Online (Sandbox Code Playgroud)

- 更新 -

正如Salvatore所提到的,在某种程度上类似于如何通过XML序列化加载的?

Sal*_*iti 5

我有一个可能的解决方案。

public class xxx
{
    private int myValue;

    [XmlElement("MyProperty")]
    public int MyPropertyForSerialization
    {
        get { return this.myValue; }
        set
        {
            Console.WriteLine("DESERIALIZED");
            this.myValue = value;
        }
    }

    [XmlIgnore]
    public int MyProperty
    {
        get { return this.myValue; }
        set
        {
            Console.WriteLine("NORMAL");
            this.myValue = value;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        xxx instance = new xxx();

        instance.MyProperty = 100; // This should print "NORMAL"

        // We serialize

        var serializer = new XmlSerializer(typeof(xxx));

        var memoryStream = new MemoryStream();
        serializer.Serialize(memoryStream, instance);

        // Let's print our XML so we understand what's going on.

        memoryStream.Position = 0;
        var reader = new StreamReader(memoryStream);
        Console.WriteLine(reader.ReadToEnd());

        // Now we deserialize

        memoryStream.Position = 0;
        var deserialized = serializer.Deserialize(memoryStream) as xxx; // This should print DESERIALIZED

        Console.ReadLine();
    }
}
Run Code Online (Sandbox Code Playgroud)

技巧是使用 XmlIgnore,它将强制 xml 序列化程序忽略我们的属性,然后我们使用 XmlElement 使用我们想要的属性名称重命名该属性以进行序列化。

这种技术的问题在于,您必须公开公共属性以进行序列化,并且在某种程度上是不好的,因为它实际上可以被每个人调用。不幸的是,如果该成员是私有的,它将不起作用。

它可以工作,并不完全干净,但是线程安全并且不依赖任何标志。

另一种可能性是使用类似 Memento 模式的东西。使用相同的技巧,您可以添加一个名为 Memento 的属性,该属性返回另一个包含仅适合序列化的属性的对象,它可以使事情变得更干净。

您是否想过不改变方法并使用 DataContractSerializer?它功能更强大并且可以生成纯 XML。它支持OnDeserializationCallback机制。