【问题标题】:Why is my abstract base class's constructor not called when an object is initialized by the WCF deserializer?为什么当 WCF 反序列化程序初始化对象时不调用我的抽象基类的构造函数?
【发布时间】:2009-08-26 10:19:31
【问题描述】:

标题中的问题...简而言之 - 我有一个 WCF 服务公开返回实体类的操作。客户端类继承自抽象基类,而不是默认的 System.Object。抽象基类定义了一个默认构造函数。在调用其中一种服务方法时,我希望在数据合同序列化程序实现返回的对象时调用该构造函数。但是,不会调用构造函数。另一方面,如果我自己创建实体类的实例,则调用抽象类构造函数。

为什么,哦,为什么,有解决方法吗?或者我错过了什么 - 在物化对象时,数据合同序列化程序是否调用了另一个构造函数签名?如果不是,datacontract 序列化程序如何在不调用构造函数的情况下实现对象,就像调用“new SomeClass()”一样?还是我今天喝了太多咖啡(目前只喝了 2 或 3 杯)?

【问题讨论】:

    标签: c# wcf serialization


    【解决方案1】:

    WCF(尤其是DataContractSerializer)不使用构造函数。不,真的(它使用FormatterServices.GetUninitializedObject 创建原始对象)。

    预计所有数据都将由序列化程序或非序列化字段初始化 - 通过您添加的序列化回调(例如,通过[OnDeserialized])。

    【讨论】:

    • 感谢您的快速回答。哇。这让我很惊讶。我认为所有对象初始化都会导致调用构造函数。哦,好吧,我今天学到了一些新东西...... :)
    • 这确实相当令人惊讶。我第一次看到它时不得不在反射器中挖掘!
    • 一个后续问题 [出于好奇] 将是:为什么他们这样做?表现?弄乱我们的脑袋?还是其他更好的理由? :)
    • 构造函数可能会做一些不恰当的事情。通过任何形式的反序列化,他们的目标不是“创建新对象”,而是“取回旧对象”。为此,您可能需要主动避开构造函数。
    • 好的,那么这是一种保护我们免受自身伤害的尝试。 :) 它完全扼杀了我一天中的工作效率。我会喝完这杯咖啡,然后我会去喝啤酒……:)
    【解决方案2】:

    我完全理解原因,但是我不明白为什么它们不支持 Silverlight 中的序列化回调。在我看来,在 WCF - Silverlight 通信中,我无法在不破解自己的情况下初始化我的数据合约。因此,如果我的基类中有一个私有成员供内部使用(例如撤消重做行为),则不能使用默认构造函数:

    Stack<PropertyChange> UndoStack = new Stack<PropertyChange>();
    

    这根本行不通。为了让它工作,我应该写这样的东西:

    Stack<PropertyChange> _UndoStack;
    Stack<PropertyChange> UndoStack
    {
         get
         {
               return _UndoStack == null ? (_UndoStack = new Stack<PropertyChange>()) : _UndoStack;
         }
    }
    

    这对我来说似乎是一种解决方法。谁有更好的主意?

    【讨论】:

    • 这似乎是一种解决方法,但您必须确保 null 检查和 setter 之间没有竞争条件,否则您可能会为一个线程返回一个陈旧的 Stack。我知道解决此问题的唯一方法是至少使用 OnDeserializing,创建一个 object syncRoot = new object() 并在 UndoStack getter 中锁定它(或直接在此方法中创建 UndoStack 实例。
    猜你喜欢
    • 2013-12-30
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多