使用DataContractSerializer时,是否可以初始化只读字段
本文关键字:初始化 读字段 是否 DataContractSerializer 使用 | 更新日期: 2023-09-27 18:25:32
DataContractSerializer
在反序列化时不调用构造函数或调用字段初始化器:
DataContractSerializer没有';t调用我的构造函数?
反序列化时C#类中的字段初始化程序未运行
使用DataContractSerializer 时设置属性的初始值
是否可以在对象反序列化后初始化readonly
字段?为了使用DataContractSerializer,我必须放弃该语言功能吗?
我不确定这样做是个好主意,但您可以通过使用反射在构造函数或字段初始值设定项之外更改readonly
字段的值。
放一些类似的东西:
typeof(MyType).GetField("Field").SetValue(this, value);
在反序列化中,回调应该可以工作。
是的,使用DataContractSerializer
可以序列化readonly
字段。您甚至可以序列化非public
readonly
字段。
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
namespace ConsoleApplication30
{
class Program
{
static void Main(string[] args)
{
Test a = new Test(1, 2);
Test b;
using (var ms = new MemoryStream())
{
DataContractSerializer ser = new DataContractSerializer(typeof(Test));
ser.WriteObject(ms, a);
ms.Position = 0;
b = (Test) ser.ReadObject(ms);
}
Trace.Assert(a.Data1 == b.Data1);
Trace.Assert(a.Data2 == b.Data2);
}
}
[DataContract]
public class Test
{
[DataMember]
public readonly int Data1;
[DataMember]
private readonly int _data2;
public int Data2
{
get { return _data2; }
}
public Test(int data1, int data2)
{
Data1 = data1;
_data2 = data2;
}
}
}
我找到了一种干净的方法,可以在不破坏设计的情况下实现您想要的目标。
使用此方法将确保调用构造函数并正确设置只读字段。
您需要的是实际序列化和反序列化DataModel类中的[DataMember]
标记字段。
这将防止在知道DataContractSerializer在反序列化时不调用构造函数的情况下发生任何意外行为。
namespace MyApp.DataModel
{
//It is not mandatory to specify the DataContract since a default one will be
//provided on recent version of .Net, however it is a good practice to do so.
[DataContract(Name = "MyClassDataModel", Namespace = "MyApp.DataModel")]
public class MyClassDataModel
{
[DataMember]
public bool DataMemberExample{ get; set; }
}
}
对于反序列化和序列化,您现在可以使用此类来保存您的值。
加载后,您可以创建一个新的数据模型对象,并将其传递给需要调用其构造函数的类。
public MyObjectThatNeedToBeConstructed LoadData(){
// ...
// get your reader (Stream) from the file system or wherever it's located
var deserializer = new DataContractSerializer(typeof(MyClassDataModel));
var storedModel = (MyClassDataModel)deserializer.ReadObject(reader);
return new MyObjectThatNeedToBeConstructed(storedModel);
}
保存后,您可以从包含ReadOnly字段的类中提取所需的数据。
public void SaveData(MyObjectThatNeedToBeConstructed myObject){
// ...
// get your writer (Stream) from memory or wherever it's located
var serializer = new DataContractSerializer(typeof(MyClassDataModel));
var dataModel = new MyClassDataModel{ DataMemberExample = myObject.DataMember};
serializer.WriteObject(writer, dataModel);
}
当然,您将不得不在构造函数中添加一个重载,并且可能需要对示例进行一些调整,但我认为您已经了解了情况。