powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Бинарная сериализация наследуемых классов
9 сообщений из 9, страница 1 из 1
Бинарная сериализация наследуемых классов
    #39570241
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет, к сожалению столкнулся со следующей проблемой.
У меня есть класс, содержащий список экземпляров других классов
Ориентировочно такой:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
    public class FakeSerializeClass : BaseViewModel
    {
    // неважно какие свойства
    }

    [Serializable]
    public class SingleTonFakeSerialized
    {
        public ObservableCollection<FakeSerializeClass> fake_sz_list { get; set; }
    }



Я хочу его бинарно сериализовать, но у меня валятся ошибки сначала что FakeSerializeClass не помечен как несериализуемый,
потом что BaseViewModel несериализуемый, потом что другие вспосмогательные классы, которые каким-либо образом задействованы в логике FakeSerializeClass ниже по иерархии.
То есть по сути бинарный сериализатор требует выставить атрибут
[Serializable] вплоть до самого верха иерархии всех классов+ всех классов, которые каким-либо образом сопряжены с ним.
Но мне нужно сериализовать только SingleTonFakeSerialized, остальные классы не должны быть сериализуемыми.

Очень странно, потому что XML-сериализатор сериализовал SingleTonFakeSerialized удачно и не требовал помечать как [Serializable] все родительские классы. Можно ли как-то избежать помечания всех классов как сериализуемые?
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570246
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,
это обыкновенное соглашение - контракт, в контексте безопасности.
попробуйте другие бинарные исполнители которые работают без это маркера..
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570265
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потому, что модель представления не предназначена для сериализации.
вы подходите к проблеме не с той стороны. Нужно подходить со стороны данных:
у меня есть данные, мне сделать сериализацию\десериализацию для них, а не у меня есть класс, мне нужно его сериализовать\десериализовать :)
есть модель данных, где это всё реализуется.
vb_sub Очень странно, потому что XML-сериализатор сериализовал SingleTonFakeSerialized удачно и не требовал помечать как [Serializable] все родительские классы
XML-сериализатор требует помечать в родительском классе атрибутом [XmlInclude(Type)] все наследуемые типы, если что.

Сделайте как нормальные люди. Создайте модель данных которая будет сериализовывать\десериализовывать данные в какие то типы. После когда загрузили\десериализовали данные создаете модель представления и передаете этот объект данных туда. В модели управляете этим объектом и если нужно сохраняете его.
Таким образом вы отделите мух от котлет и меня модель представления это не будет отражаться на формате данных с которым работает ваша программа, а люди которые потом будут сопровождать это, не будут ломать голову и вспоминать вас плохим словом :)
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570368
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes,
то есть если XML-сериализатор может сериализовать класс вместе с его внутренней структурой( например вложенные иерархические элементы), то для бинарного необходимо все преобразовать в набор простых типов данных, убрать всю иерархию элементов внутри класса и тд?
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570391
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,

Можно извернуться с помощью SurrogateSelector'а:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
class Program
{
  static void Main()
  {
    var bar = new Bar
    {
      Name = "bar",
      Zot = 123
    };
    Console.WriteLine(bar);
    byte[] data;
    using(var ms = new MemoryStream())
    {
      var bf = new BinaryFormatter();
      var surrogateTypes = new[] { typeof(Bar) };
      var ss = new SurrogateSelector();
      foreach(var t in surrogateTypes)
        ss.AddSurrogate(t, new StreamingContext(StreamingContextStates.All), new NonSerialiazableTypeSurrogate());
      bf.SurrogateSelector = ss;
      bf.Serialize(ms, bar);
      data = ms.ToArray();
    }
    using (var ms = new MemoryStream(data))
    {
      var bf = new BinaryFormatter();
      var surrogateTypes = new[] { typeof(Bar) };
      var ss = new SurrogateSelector();
      foreach (var t in surrogateTypes)
        ss.AddSurrogate(t, new StreamingContext(StreamingContextStates.All), new NonSerialiazableTypeSurrogate());
      bf.SurrogateSelector = ss;
      var bar2 = bf.Deserialize(ms) as Bar;
      Console.WriteLine(bar2?.ToString() ?? "null");
      
    }
    Console.WriteLine("done");
    Console.ReadKey(true);
  }
}

class Foo
{
  public int Zot { get; set; }
}

[Serializable]
class Bar : Foo
{
  public string Name { get; set; }
  public override string ToString()
  {
    return string.Concat(Name, "#", Zot);
  }
}

internal class NonSerialiazableTypeSurrogate : ISerializationSurrogate
{
  public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
  {
    GetObjectData(obj.GetType(), obj, info);
  }

  static void GetObjectData(Type type, object obj, SerializationInfo info)
  {
    var fieldInfos = type.GetFields(
      BindingFlags.Instance |
      BindingFlags.Public |
      BindingFlags.NonPublic);
    foreach (var fi in fieldInfos)
      if (IsKnownType(fi.FieldType))
        info.AddValue(fi.Name, fi.GetValue(obj));
      else if (fi.FieldType.IsClass)
        info.AddValue(fi.Name, fi.GetValue(obj));
    var bt = type.BaseType;
    if (bt!=typeof(object))
      GetObjectData(bt, obj, info);
  }

  public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
  {
    SetObjectData(obj.GetType(), obj, info);
    return obj;
  }

  static void SetObjectData(Type type, object obj, SerializationInfo info)
  {
    var fieldInfos = type.GetFields(
      BindingFlags.Instance |
      BindingFlags.Public |
      BindingFlags.NonPublic);
    foreach (var fi in fieldInfos)
    {
      if (IsKnownType(fi.FieldType))
      {
        if (IsNullableType(fi.FieldType))
        {
          var argumentValueForTheNullableType = GetFirstArgumentOfGenericType(fi.FieldType);
          fi.SetValue(obj, info.GetValue(fi.Name, argumentValueForTheNullableType));
        }
        else
          fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
      }
      else if (fi.FieldType.IsClass)
        fi.SetValue(obj, info.GetValue(fi.Name, fi.FieldType));
    }
    var bt = type.BaseType;
    if (bt != typeof(object))
      SetObjectData(bt, obj, info);
  }

  static Type GetFirstArgumentOfGenericType(Type type)
  {
    return type.GetGenericArguments()[0];
  }

  static bool IsNullableType(Type type)
  {
    if (type.IsGenericType)
      return type.GetGenericTypeDefinition() == typeof(Nullable<>);
    return false;
  }

  static bool IsKnownType(Type type)
  {
    return type == typeof(string) ||
           type.IsPrimitive ||
           type.IsSerializable;
  }
}


консольный вывод:
Код: plaintext
1.
bar#123
bar#123
Но, как выше писал Роман, у вас налицо смешивание вьюмодели и модели, что не есть хорошо.
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570400
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вот вам пример, бинарная сериализация, абстрактный класс, с иерархией, всё работает
у вас проблема только в том, что вы пытаетесь десериализовывать модель представления, что в корне неверно
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace BinSerialize
{
    [Serializable]
    public abstract class Person
    {
        public string Name { set; get; }
        public int Age { set; get; }
        public Person[] Dependent { set; get; }
    }

    [Serializable]
    public class Employer : Person
    {
        public string Title { set; get; }

        public override string ToString()
        {
            return $"{Name}, {Age}, {Title}";
        }
    }


    [Serializable]
    public class Children : Person
    {
        public DateTime Birthday { set; get; }

        public override string ToString()
        {
            return $"{Name}, {Age}, {Birthday:d}";
        }
    }

    internal class Program
    {
        private static readonly BinaryFormatter BinFormater = new BinaryFormatter();

        private static void Serialize(Person person, string filename)
        {
            using (Stream fStream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                BinFormater.Serialize(fStream, person);
            }
        }

        private static Person Deserialize(string filename)
        {
            using (Stream fStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None))
            {
                return (Person)BinFormater.Deserialize(fStream);
            }
        }


        static void Main()
        {
            //Создаем объект
            Person person = new Employer
            {
                Name = "Roman Meytes",
                Age = 35,
                Title = "Developer",
                Dependent = new Person[]
                {
                    new Children
                    {
                        Name = "Olga Meytes",
                        Age = 8,
                        Birthday = new DateTime(2008, 12, 21)
                    },
                    new Employer
                    {
                        Name = "Ivan Ivanov",
                        Age = 45,
                        Title = "Lead developer"
                    }
                }
            };
            //Сохраняем\сериализуем в файл
            Serialize(person, @"user.dat");

            //Загружаем из файла объект
            Person employer = Deserialize(@"user.dat");
            //Отображаем на экране
            Console.WriteLine(employer);
            foreach (var child in employer.Dependent)
            {
                Console.Write("\t");
                Console.WriteLine(child);
            }
            Console.WriteLine("Press any key to continue");
            Console.ReadKey();
        }
    }
}



Результат выполнения:
Код: plaintext
1.
2.
3.
Roman Meytes, 35, Developer
        Olga Meytes, 8, 12/21/2008
        Ivan Ivanov, 45, Lead developer
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570411
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesвот вам пример, бинарная сериализация, абстрактный класс, с иерархией, всё работает
у вас проблема только в том, что вы пытаетесь десериализовывать модель представления, что в корне неверно
Ну, если в обычной модели данных в иерархии будут классы без атрибута сериализации, то это не взлетит без доп. усилий.
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39570427
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

ну очевидно, что атрибут должен быть.
если есть тип в модели, у которого такого атрибута нет и он доступен только из готовой сборки, то можно просто обернуть его своим типом, не особо сложная операция, если объект конечно не очень большой.
Ну, а если он большой и сложный, то можно создать полностью свою модель, а после загрузки уже инициализировать нужные классы модели.
а потом на всё этом создавать модель представления из которой управлять всем этим варевом )
...
Рейтинг: 0 / 0
Бинарная сериализация наследуемых классов
    #39571333
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtes,

спасибо за пример.
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Бинарная сериализация наследуемых классов
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]