反序列化时不运行 C# 类中的字段初始值设定项 [英] Field Initializer in C# Class not Run when Deserializing
问题描述
我有一个定义受保护字段的类.受保护的字段有一个字段初始值设定项.
I have a class that defines a protected field. The protected field has a field initializer.
当我反序列化具体类时,不会运行字段初始值设定项.为什么?解决问题的最佳模式是什么?如果我将初始化移动到构造函数中,构造函数也不会被调用.
When I deserialize the concrete class, the field initializer is not run. Why? What is the best pattern to solve the problem? If I move the initialization into a constructor, the constructor is also not invoked.
[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
}
}
原始类层次结构
[DataContract]
public abstract class MyAbstract
{
// THIS INITIALIZER IS NOT RUN WHILE DESERIALIZING:
protected readonly Dictionary<int, string> 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
}
}
[DataContract]
public class MyConcrete : MyAbstract
{
}
class Program
{
static void Main(string[] args)
{
string tempfn = Path.GetTempFileName();
MyConcrete concrete = new MyConcrete() { MyProp = 42 };
string data = concrete.SerializeToString<MyConcrete>();
MyConcrete rehydrated = SerializationHelper.DeserializeFromString<MyConcrete>(data);
}
}
支持方法
static public string SerializeToString<T>(this T obj)
{
return SerializationHelper.SerializeToString<T>(obj);
}
static public string SerializeToString<T>(T obj)
{
DataContractSerializer s = new DataContractSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
s.WriteObject(ms, obj);
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
string serialized = sr.ReadToEnd();
return serialized;
}
}
}
static public T DeserializeFromString<T>(string serializedDataAsString)
{
DataContractSerializer s = new DataContractSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(serializedDataAsString)))
{
object s2 = s.ReadObject(ms);
return (T)s2;
}
}
推荐答案
关于反序列化 既不调用构造函数,也不调用字段初始化器 并改为使用空白"未初始化对象.
On deserialization neither the constructors nor the field initializers are called and a "blank" un-initialized object is used instead.
要解决它,您可以使用 OnDeserializing
或 OnDerserialized
属性让反序列化器调用具有以下签名的函数:
To resolve it you can make use of the OnDeserializing
or OnDerserialized
attributes to have the deserializer call a function with the following signature:
void OnDeserializing(System.Runtime.Serialization.StreamingContext c);
在该函数中,您可以初始化反序列化过程中遗漏的任何内容.
In that function is where you can initialize whatever was missed within the deserialization process.
就约定而言,我倾向于让我的构造函数调用一个方法 OnCreated()
,然后也让反序列化方法调用相同的东西.然后,您可以在那里处理所有字段初始化,并确保它在反序列化之前被触发.
In terms of convention, I tend to have my constructor call a method OnCreated()
and then also have deserializating method call the same thing. You can then handle all of the field initialization in there and be sure it's fired before deserialization.
[DataContract]
public abstract class MyAbstract
{
protected Dictionary<int, string> myDict;
protected MyAbstract()
{
OnCreated();
}
private void OnCreated()
{
myDict = new Dictionary<int, string>();
}
[OnDeserializing]
private void OnDeserializing(StreamingContext c)
{
OnCreated();
}
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; }
}
}
这篇关于反序列化时不运行 C# 类中的字段初始值设定项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!