我刚刚意识到一些疯狂的东西,我认为这是完全不可能的:当反序列化一个对象时,DataContractSerializer不会调用构造函数!
以这门课为例,例如:
[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; }
}
Run Code Online (Sandbox Code Playgroud)
当我反序列化该类的对象时,不会触发断点.我完全不知道它是如何可能的,因为它是这个对象的唯一构造函数!
我假设编译器可能因为DataContract属性而生成了额外的构造函数,但我无法通过反射找到它...
所以,我想知道的是:如何在不调用构造函数的情况下创建我的类的实例?
注意:我知道OnDeserializing在反序列化开始时我可以使用该属性初始化我的对象,这不是我的问题的主题.
我有一个定义受保护字段的类.受保护的字段具有字段初始值设定项.
当我反序列化具体类时,不会运行字段初始值设定项.为什么?解决问题的最佳模式是什么?如果我将初始化移动到构造函数中,也不会调用构造函数.
[DataContract]
public class MyConcrete
{
// FIELD INITIALIZER DOES NOT RUN WHEN COMMENTED IN:
protected readonly Dictionary<int, string> myDict;// = new Dictionary<int, string>();
public MyConcrete()
{
myDict = new Dictionary<int, string>();
}
private bool MyMethod(int key)
{
return myDict.ContainsKey(key);
}
private int myProp;
[DataMember]
public int MyProp
{
get { return myProp; }
set { bool b = MyMethod(value); myProp = value; } // Call MyMethod to provoke error
}
}
Run Code Online (Sandbox Code Playgroud)
原始类层次结构
[DataContract]
public abstract class MyAbstract
{ …Run Code Online (Sandbox Code Playgroud) 如果我正在序列化并稍后反序列化类,DataContractSerializer我如何控制未序列化的属性的初始值?
考虑下面的Person课程.它的数据协定设置为序列化FirstName和LastName属性,但不是IsNew属性.我想IsNew初始化为TRUE是否将新Person实例化为新实例或从文件反序列化.
这很容易通过构造函数来完成,但据我所知,它DataContractSerializer不会调用构造函数,因为它们可能需要参数.
[DataContract(Name="Person")]
public class Person
{
[DataMember(Name="FirstName")]
public string FirstName { get; set; }
[DataMember(Name = "LastName")]
public string LastName { get; set; }
public bool IsNew { get; set; }
public Person(string first, string last)
{
this.FirstName = first;
this.LastName = last;
this.IsNew = true;
}
}
Run Code Online (Sandbox Code Playgroud)