使用DataContractSerializer时,是否可以初始化只读字段

本文关键字:初始化 读字段 是否 DataContractSerializer 使用 | 更新日期: 2023-09-27 18:25:32

DataContractSerializer在反序列化时不调用构造函数或调用字段初始化器:

DataContractSerializer没有';t调用我的构造函数?

反序列化时C#类中的字段初始化程序未运行

使用DataContractSerializer 时设置属性的初始值

是否可以在对象反序列化后初始化readonly字段?为了使用DataContractSerializer,我必须放弃该语言功能吗?

使用DataContractSerializer时,是否可以初始化只读字段

我不确定这样做是个好主意,但您可以通过使用反射在构造函数或字段初始值设定项之外更改readonly字段的值。

放一些类似的东西:

typeof(MyType).GetField("Field").SetValue(this, value);

在反序列化中,回调应该可以工作。

是的,使用DataContractSerializer可以序列化readonly字段。您甚至可以序列化非publicreadonly字段。

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);
}

当然,您将不得不在构造函数中添加一个重载,并且可能需要对示例进行一些调整,但我认为您已经了解了情况。