C# 未在反序列化时调用构造函数

C# 未在反序列化时调用构造函数,c#,deserialization,datacontractjsonserializer,C#,Deserialization,Datacontractjsonserializer,我读过的许多地方都指出,在反序列化时,.NET Framework会调用,其中不调用构造函数,也不设置字段初始值设定项。如果这是真的,为什么要调用我的构造函数?是否存在可以调用构造函数和字段初始值设定项的实例 我的班级: [DataContract] public class TestClass { [DataMember] public string Val1 { get; set; } [DataMember] public string Val2 { ge

我读过的许多地方都指出,在反序列化时,.NET Framework会调用,其中不调用构造函数,也不设置字段初始值设定项。如果这是真的,为什么要调用我的构造函数?是否存在可以调用构造函数和字段初始值设定项的实例

我的班级:

[DataContract]
public class TestClass
{
    [DataMember]
    public string Val1 { get; set; }

    [DataMember]
    public string Val2 { get; set; }

    [DataMember]
    public bool NonDefaultBool = true;

    private int _nonDefaultInt = 1234;

    [DataMember]
    public int NonDefaultInt
    {
        get { return _nonDefaultInt; }
        set { _nonDefaultInt = value; }
    }

    public TestClass()
    {
        Val1 = "hello";
    }
}
我的反序列化代码:

var json2 =
@"{
    ""Val1"":""hello""
}";

using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json2)))
{
    var thing = DeserializeJsonObject<TestClass>(ms);
    Console.WriteLine(GetSerializedData(thing));
}

// ... code left out

protected static TModel DeserializeJsonObject<TModel>(Stream data) where TModel : class
{
    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(TModel));
    return jsonSerializer.ReadObject(data) as TModel;
}

static string GetSerializedData<T>(T data)
{
    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(T), _knownTypes);

    using (MemoryStream ms = new MemoryStream())
    {
        jsonSerializer.WriteObject(ms, data);
        return Encoding.UTF8.GetString(ms.ToArray());
    }
}

您正在反序列化json2字符串

var json2=
@“{
“Val1”:“你好”
}";


我认为没有调用构造函数,但“hello”是由JSON字符串分配的。

以防它对其他人有用。答案是在数据契约上提供[OnDeserialization]处理程序。在您的情况下,实现如下所示:

[DataContract]
public class TestClass
{
    [DataMember]
    public string Val1 { get; set; }

    [DataMember]
    public string Val2 { get; set; }

    [DataMember]
    public bool NonDefaultBool;

    [DataMember]
    public int NonDefaultInt { get; set; }

    private void InitializeDefaults()
    {
        Val1 = "hello";
        NonDefaultBool = true;
        NonDefaultInt = 1234;
    }

    #region Construction

    public TestClass()
    {
        InitializeDefaults();
    }

    [OnDeserializing]
    private void OnDeserializing(StreamingContext context)
    {
        InitializeDefaults();
    }

    #endregion
}

好的,在再次抱怨之后,我提出了一个解决方案,如果您愿意继承基类,并且不太在意使用反射:

[DataContract]
class ConstructedDataContract
{
    [OnDeserializing]
    void OnDeserializing(StreamingContext context)
    {
        ConstructorInfo ci = this.GetType().GetConstructor(new Type[] { });
        if (ci != null)
        {
            ci.Invoke(this, new object[] { });
        }
    }
}
然后只继承那个基类

[DataContract]
class MyClass1 : ConstructedDataContract
{
    [DataMember(IsRequired=false)]
    public int Var1 = 5; // This will initialise to 5, and if the field is
                         // included in the serialisation stream, then it 
                         // will be overwritten.
}

将对基类调用OnDeserialization,基类将使用反射来运行类的默认构造函数。在上述情况下,默认构造函数将Var1设置为5,即使没有显式构造函数块。如果有,那么来自该块的代码也将被执行。

您能显示GetSerializedData代码吗?啊。是的,构造函数应该分配给Val2。不过,这个问题确实出现了,因为我有另一个实例,其中字段初始值设定项似乎被调用。但这是另一个问题。
[DataContract]
class MyClass1 : ConstructedDataContract
{
    [DataMember(IsRequired=false)]
    public int Var1 = 5; // This will initialise to 5, and if the field is
                         // included in the serialisation stream, then it 
                         // will be overwritten.
}