保留限制性访问修饰符并使 class 可序列化
Preserving restrictive access modifiers and making a class serializable
我正在尝试制作一个 class 我写的可序列化的。它包含几个构造后永远不会改变的静态只读字段,因此不需要序列化。我很难找到一种在反序列化后不会削弱基础 class 中的访问权限的方法来重新设置它们。这是一个简化的示例,从不可序列化的基础开始并派生 class:
internal abstract class MyBase
{
private readonly List<int> myIntList = new List<int> ();
internal MyBase (List<int> anIntList)
{
this.myIntList = anIntList;
}
}
派生class不需要访问列表,所以该字段在基class中可以是private readonly,派生class这样设置:
internal sealed class MyDerived : MyBase
{
private static readonly List<int> derivedIntList = new List<int> { 1, 2, 3 };
internal MyDerived () : base (MyDerived.derivedIntList)
{
}
}
现在我想让派生的 class 可序列化。由于列表内容没有改变,因此不需要序列化它们,所以我只是在两个 classes.
上都放置了一个 DataContract 属性
我将派生的 class 序列化到磁盘,如下所示:
private static void SeralizeDerived (string path)
{
MyDerived derived = new MyDerived ();
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Create))
{
serializer.WriteObject (stream, derived);
stream.Flush ();
}
}
并像这样反序列化它:
private static void DeserializeDerived (string path)
{
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Open, FileAccess.Read))
{
MyDerived derived = serializer.ReadObject (stream) as MyDerived;
// debugger shows derived.myIntList as null, as expected
}
}
根据 DeserializeDerived 中的注释,derived.myIntList 的值为 null。这对我来说并不奇怪——我没有要求它被序列化,我也没有做任何事情来在反序列化后重新创建它。
问题是这样的:我知道解决此问题的唯一方法是更改对 myIntList 的访问以使其受到保护,并在 MyDerived class 中使用 OnDeserialized 方法(重新)设置 myIntList:
private void ReInitialize ()
{
base.myIntList = MyDerived.derivedIntList;
}
[OnDeserialized]
private void OnDeserialized (StreamingContext context)
{
this.ReInitialize ();
}
internal MyDerived () : base ()
{
this.ReInitialize ();
}
这感觉不对——我不想弱化对基 class 成员的访问,在派生构造函数中逐字段初始化成员更容易出错。问题是:如何在保持会员保护不变的同时还支持连载?
将静态列表传递到基础 class 构造函数对我来说很奇怪。我会说这里的继承有问题。
如果你仍然想使用抽象的继承尝试方法 属性:
public abstract class Data
{
public abstract int[] list { get;}
}
public class Data2 : Data
{
private static readonly int[] arr = new[] {1,2,3};
public override int[] list { get => arr; }
}
我正在尝试制作一个 class 我写的可序列化的。它包含几个构造后永远不会改变的静态只读字段,因此不需要序列化。我很难找到一种在反序列化后不会削弱基础 class 中的访问权限的方法来重新设置它们。这是一个简化的示例,从不可序列化的基础开始并派生 class:
internal abstract class MyBase
{
private readonly List<int> myIntList = new List<int> ();
internal MyBase (List<int> anIntList)
{
this.myIntList = anIntList;
}
}
派生class不需要访问列表,所以该字段在基class中可以是private readonly,派生class这样设置:
internal sealed class MyDerived : MyBase
{
private static readonly List<int> derivedIntList = new List<int> { 1, 2, 3 };
internal MyDerived () : base (MyDerived.derivedIntList)
{
}
}
现在我想让派生的 class 可序列化。由于列表内容没有改变,因此不需要序列化它们,所以我只是在两个 classes.
上都放置了一个 DataContract 属性我将派生的 class 序列化到磁盘,如下所示:
private static void SeralizeDerived (string path)
{
MyDerived derived = new MyDerived ();
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Create))
{
serializer.WriteObject (stream, derived);
stream.Flush ();
}
}
并像这样反序列化它:
private static void DeserializeDerived (string path)
{
DataContractSerializer serializer = new DataContractSerializer (typeof (MyDerived));
using (FileStream stream = new FileStream (path, FileMode.Open, FileAccess.Read))
{
MyDerived derived = serializer.ReadObject (stream) as MyDerived;
// debugger shows derived.myIntList as null, as expected
}
}
根据 DeserializeDerived 中的注释,derived.myIntList 的值为 null。这对我来说并不奇怪——我没有要求它被序列化,我也没有做任何事情来在反序列化后重新创建它。
问题是这样的:我知道解决此问题的唯一方法是更改对 myIntList 的访问以使其受到保护,并在 MyDerived class 中使用 OnDeserialized 方法(重新)设置 myIntList:
private void ReInitialize ()
{
base.myIntList = MyDerived.derivedIntList;
}
[OnDeserialized]
private void OnDeserialized (StreamingContext context)
{
this.ReInitialize ();
}
internal MyDerived () : base ()
{
this.ReInitialize ();
}
这感觉不对——我不想弱化对基 class 成员的访问,在派生构造函数中逐字段初始化成员更容易出错。问题是:如何在保持会员保护不变的同时还支持连载?
将静态列表传递到基础 class 构造函数对我来说很奇怪。我会说这里的继承有问题。
如果你仍然想使用抽象的继承尝试方法 属性:
public abstract class Data
{
public abstract int[] list { get;}
}
public class Data2 : Data
{
private static readonly int[] arr = new[] {1,2,3};
public override int[] list { get => arr; }
}