简体   繁体   English

DataContractSerializer 不调用我的构造函数?

[英]DataContractSerializer doesn't call my constructor?

I just realized something crazy, which I assumed to be completely impossible : when deserializing an object, the DataContractSerializer doesn't call the constructor !我刚刚意识到一些疯狂的事情,我认为这是完全不可能的:反序列化对象时, DataContractSerializer 不会调用构造函数

Take this class, for instance :以这个类为例:

[DataContract]
public class Book
{
    public Book()
    { // breakpoint here
    }

    [DataMember(Order = 0)]
    public string Title { get; set; }
    [DataMember(Order = 1)]
    public string Author { get; set; }
    [DataMember(Order = 2)]
    public string Summary { get; set; }
}

When I deserialize an object of that class, the breakpoint is not hit.当我反序列化那个类的对象时,断点没有被命中。 I have absolutely no idea how it is possible, since it is the only constructor for this object !我完全不知道这是怎么可能的,因为它是这个对象的唯一构造函数!

I assumed that perhaps an additional constructor was generated by the compiler because of the DataContract attribute, but I couldn't find it through reflection...我假设编译器可能因为DataContract属性而生成了一个额外的构造函数,但是我无法通过反射找到它...

So, what I'd like to know is this : how could an instance of my class be created without the constructor being called ??所以,我想知道的是:如何在不调用构造函数的情况下创建我的类的实例?

NOTE: I know that I can use the OnDeserializing attribute to initialize my object when deserialization begins, this is not the subject of my question.注意:我知道我可以在反序列化开始时使用OnDeserializing属性来初始化我的对象,这不是我的问题的主题。

DataContractSerializer (like BinaryFormatter ) doesn't use any constructor. DataContractSerializer (如BinaryFormatter )不使用任何构造函数。 It creates the object as empty memory.它将对象创建为空内存。

For example:例如:

    Type type = typeof(Customer);
    object obj = System.Runtime.Serialization.
        FormatterServices.GetUninitializedObject(type);

The assumption is that the deserialization process (or callbacks if necessary) will fully initialize it.假设是反序列化过程(或必要时回调)将完全初始化它。

There are some scenario's that wouldn't be possible without this behavior.如果没有这种行为,有些情况是不可能的。 Think of the following:考虑以下几点:

1) You have an object that has one constructor that sets the new instance to an "initialized" state. 1) 您有一个对象,该对象具有一个构造函数,该构造函数将新实例设置为“已初始化”状态。 Then some methods are called on that instance, that bring it in a "processed" state.然后在该实例上调用一些方法,使其处于“已处理”状态。 You don't want to create new objects having the "processed" state, but you still want de serialize / deserialize the instance.您不想创建具有“已处理”状态的新对象,但您仍希望对实例进行反序列化/反序列化。

2) You created a class with a private constructor and some static properties to control a small set of allowed constructor parameters. 2) 您创建了一个带有私有构造函数和一些静态属性的类来控制一小组允许的构造函数参数。 Now you can still serialize / deserialize them.现在您仍然可以序列化/反序列化它们。

XmlSerializer has the behavior you expected. XmlSerializer 具有您预期的行为。 I have had a some problems with the XmlSerializer because it DOES need a default constructor.我在使用 XmlSerializer 时遇到了一些问题,因为它确实需要一个默认构造函数。 Related to that, sometimes it makes sense to have private property setters.与此相关,有时拥有私有财产设定者是有意义的。 But the XmlSerializer also needs public getter and setter on properties in order to serialize / deserialize.但是 XmlSerializer 还需要属性上的公共 getter 和 setter,以便序列化/反序列化。

I think of the DataContractSerializer / BinaryFormatter behavior like suspending the state of an instance during serialization and resuming during deserialization.我想到了 DataContractSerializer / BinaryFormatter 行为,例如在序列化期间暂停实例的状态并在反序列化期间恢复。 In other words, the instances are not “constructed” but “restored” to an earlier state.换句话说,实例不是“构造”而是“恢复”到较早的状态。

As you already mentioned, the [OnDeserializing] attribute makes it possible to keep non serialized data in sync.正如您已经提到的,[OnDeserializing] 属性可以使非序列化数据保持同步。

FWIW, you can call the constructor explicitly from a [OnDeserializing] method: FWIW,您可以从 [OnDeserializing] 方法显式调用构造函数:

[OnDeserializing]
public void OnDeserializing(StreamingContext context)
{
    this.GetType().GetConstructor(System.Array.Empty<Type>()).Invoke(this, null);
}

Use [OnDeserialized] attribute to initialise your properties.使用 [OnDeserialized] 属性来初始化您的属性。

// This method is called after the object
// is completely deserialized. Use it instead of the
// constructror.
[OnDeserialized]
void OnDeserialized(StreamingContext context)
{
    fullName = firstName + " " + lastName;
}

Please refer to microsoft guid-lines: https://docs.microsoft.com/en-us/dotnet/standard/serialization/serialization-guidelines请参考微软指南: https : //docs.microsoft.com/en-us/dotnet/standard/serialization/serialization-guidelines

In my case, i wanted to create an object to use in a lock-clause.就我而言,我想创建一个对象以在锁定子句中使用。 I tried implementing IDeserializationCallback (didn't work because callback only runs after properties have been assigned), [OnDeserialized] (didn't work, same previous reason), and ISerializable (didn't work because the class is decorated with the [DataContractAttribute]).我尝试实现 IDeserializationCallback(不起作用,因为回调仅分配属性运行)、[OnDeserialized](不起作用,与之前的原因相同)和 ISerializable(不起作用,因为该类用 [DataContractAttribute ])。

My workaround was to initialize the field before it's used using Interlocked.CompareExchange.我的解决方法是在使用 Interlocked.CompareExchange 之前初始化该字段。 A bit of unnecessary work gets done, but at least now my field gets initialized when a DataContractSerializer creates it.一些不必要的工作已经完成,但至少现在我的字段在 DataContractSerializer 创建它时被初始化。

Interlocked.CompareExchange(ref _sync, new object(), null);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Datacontractserializer不会覆盖所有数据 - Datacontractserializer doesn't overwrite all data AddDbContext 不调用 DbContext 构造函数 - AddDbContext doesn't call DbContext constructor 如果注释掉成员的构造函数调用,为什么我的程序不起作用? - Why doesn't my program work if I comment out a member's constructor call? Visual Studio无法识别我的构造函数? - Visual studio doesn't recognize my constructor? 为什么我不应该在构造函数中调用我的依赖项? - Why shouldn't I call my dependencies from within the constructor? 为什么我的C#基本构造函数没有被调用? - why doesn't my c# base constructor get called? DataContractSerializer 需要抽象基础 class 中的无参数构造函数 - DataContractSerializer requires parameterless constructor in abstract base class 如何配置WebAPI和DataContractSerializer,使其不关心元素的顺序? - How to configure WebAPI and DataContractSerializer so that it doesn't care about the Ordering of the elements? 为什么我的KendoGrid不叫我的MVC控制器? - Why doesn't my KendoGrid call my MVC controller? 为什么我的Ajax调用无法到达我的.NET WebMethod? - Why doesn't my ajax call reach my .NET WebMethod?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM