Ошибка при выводе на консоль после десериализация List, со вложенной структурой
Есть list классов со вложенной структурой. Вот Экземпляр класса родителя(Классы наследники почти не отличаются).
[Serializable(), XmlInclude(typeof(Triangle)), XmlInclude(typeof(Quadrangle)),XmlInclude(typeof(Top))]
public abstract class Figure : Comp
{
string name;
Top a, b, c, d;
Top[] Tops;
public Color colorFigure;
public List<Figure> FigureList = new List<Figure>();
public Figure()
{ }
public Figure(Top a, Top b, Top c, Color colorFigure)
{
A = a;
B = b;
C = c;
ColorFigure = colorFigure;
Tops = new Top[3] { A, B, C };
}
public Figure(Top a, Top b, Top c, Top d, Color colorFigure)
{
A = a;
B = b;
C = c;
D = d;
ColorFigure = colorFigure;
Tops = new Top[4] { A, B, C, D };
}
public string Name { get => name; set => name = value; }
public Top A { get => a; set => a = value; }
public Top B { get => b; set => b = value; }
public Top C { get => c; set => c = value; }
public Top D { get => d; set => d = value; }
public Color ColorFigure { get => colorFigure; set => colorFigure = value; }
public abstract double Area();
public abstract double Perimeter();
public void ShowInfo()
{
var cc = ClosestConsoleColor(ColorFigure.R, ColorFigure.G, ColorFigure.B);
Console.ForegroundColor = cc;
Console.ForegroundColor = cc;
Console.WriteLine(Name);
Console.WriteLine($"Color {ColorFigure}");
Console.WriteLine("Coordinates");
foreach (Top top in Tops)
{
Console.WriteLine($"{top.X}, {top.Y}");
}
Console.WriteLine($"Perimeter = {Perimeter()}");
Console.WriteLine($"Area = {Area()}");
Console.ResetColor();
Console.WriteLine();
}
//это не мой код, ядом не надо поливать
protected ConsoleColor ClosestConsoleColor(byte r, byte g, byte b)
{
ConsoleColor ret = 0;
double rr = r, gg = g, bb = b, delta = double.MaxValue;
foreach (ConsoleColor cc in Enum.GetValues(typeof(ConsoleColor)))
{
var n = cc.ToString();//Enum.GetName(typeof(ConsoleColor), cc);
var c = System.Drawing.Color.FromName(n == "DarkYellow" ? "Orange" : n); // bug fix
var t = Math.Pow(c.R - rr, 2.0) + Math.Pow(c.G - gg, 2.0) + Math.Pow(c.B - bb, 2.0);
if (t == 0.0)
return cc;
if (t < delta)
{
delta = t;
ret = cc;
}
}
return ret;
}
//Теперь снова мой)
public double SideLength(Top a, Top b)
{
return Math.Sqrt((Math.Pow((a.X - b.X), 2)) + (Math.Pow((a.Y - b.Y), 2)));
}
public List<Figure> ReadAndDeserialize()
{
var serializer = new XmlSerializer(typeof(List<Figure>));
using (var sr = new StreamReader("searilize.txt"))
{
return (List<Figure>)serializer.Deserialize(sr);
}
}
public void SerializeAndSave(List<Figure> data)
{
var serializer = new XmlSerializer(typeof(List<Figure>));
using (var sw = new StreamWriter("searilize.txt", true))
{
serializer.Serialize(sw, data);
}
}
public void SerializeAndRewritingSave(List<Figure> data)
{
var serializer = new XmlSerializer(typeof(List<Figure>));
using (var sw = new StreamWriter("searilize.txt"))
{
serializer.Serialize(sw, data);
}
}
}
[Serializable]
public struct Top
{
int x, y;
public Top(int x, int y) : this()
{
X = x;
Y = y;
}
public int X { get => x; set => x = value; }
public int Y { get => y; set => y = value; }
}
}
Сериализация List проходит не полностью, во первых не сохраняется цвет экземпляра класса. Во вторых после десериализации метод "public void ShowInfo()" выводит ошибку "System.NullReferenceException: "Ссылка на объект не указывает на экземпляр объекта. <Временное локальное типа "FigureLib.Top[]"> было null." на строке
foreach (Top top in Tops)
{
Console.WriteLine($"{top.X}, {top.Y}");
}
Как исправить? Заранее спасибо!
Ответы (1 шт):
Итак. Основных вопроса было два. Первый - ошибка в ShowInfo() после десериализации, в частности на моменте исполнения foreach (Top top in Tops). Второй - потеря значения Color при сериализации.
Ответ на первый вопрос. Дело в том, что значения структур Top сохранялось, но я не добавил модификатор доступа к массив Top[], из-за чего он был приватный(по умолчанию) и не сериализовался. Добавив модификатор доступа public к Top[], все заработало.
Ответ на второй вопрос. Если я правильно вычитал, то System.Drawing.Color является иммутабельным(не понял правда в чем это выражено), то есть Color будет readonly, из-за чего и не сериализуестя. Ответ нашел вот тут https://www.cyberforum.ru/csharp-beginners/thread2444304.html Легкая модификация
[XmlIgnore]
public Color ColorFigure { get => colorFigure; set => colorFigure = value; }
/// <summary>
/// Method to serialize color
/// </summary>
[XmlElement("Color")] // Или Attribute
public int ColorSerialized
{
get => ColorFigure.ToArgb();
set => ColorFigure = Color.FromArgb(value);
}
и у меня все работает.