Сохранение модификаторов ограниченного доступа и создание сериализуемого класса - PullRequest
0 голосов
/ 09 июля 2019

Я пытаюсь сделать класс, который я написал, сериализуемым. Он содержит несколько статических полей только для чтения, которые никогда не меняются после создания, поэтому их не нужно сериализовать. У меня проблемы с поиском способа переустановить их после десериализации, что не ослабляет доступ в базовом классе. Вот упрощенный пример, начиная с несериализуемой базы и производного класса:

internal abstract class MyBase
{
    private readonly List<int> myIntList = new List<int> ();

    internal MyBase (List<int> anIntList)
    {
        this.myIntList = anIntList;
    }
}

Производному классу не требуется доступ к списку, поэтому поле может быть доступно только для чтения в базовом классе, а производный класс устанавливает его следующим образом:

internal sealed class MyDerived : MyBase
{
    private static readonly List<int> derivedIntList = new List<int> { 1, 2, 3 };

    internal MyDerived () : base (MyDerived.derivedIntList)
    {
    }
}

Теперь я хочу сделать мой производный класс сериализуемым. Поскольку содержимое списка не меняется, их не нужно сериализовать, поэтому я просто помещаю атрибут DataContract в оба класса.

Я сериализирую производный класс на диск следующим образом:

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, значение output.myIntList равно нулю. Это не удивительно для меня - я не просил его сериализовать, и я ничего не сделал, чтобы воссоздать его после десериализации.

Проблема заключается в следующем: единственный известный мне способ исправить это - изменить доступ к myIntList, чтобы сделать его защищенным, и иметь метод OnDeserialized в классе MyDerived, который (пере) устанавливает myIntList:

private void ReInitialize ()
{
    base.myIntList = MyDerived.derivedIntList;
}

[OnDeserialized]
private void OnDeserialized (StreamingContext context)
{
    this.ReInitialize ();
}

internal MyDerived () : base ()
{
    this.ReInitialize ();
}

Это кажется неправильным - я не хочу ослаблять доступ к членам базового класса, и инициализация полевых элементов в производном конструкторе более подвержена ошибкам. Вопрос в том, как сохранить ту же защиту членов, но при этом поддерживать сериализацию?

1 Ответ

0 голосов
/ 09 июля 2019

Передача статического списка в конструктор базового класса выглядит странно для меня.Я бы сказал, что здесь что-то не так с наследованием.

Если вы все еще хотите использовать наследование, попробуйте подход с абстрактным свойством:

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