Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/5: Рейтинг темы: голосов - 5, средняя оценка - 5.00
Mirmik
techpriest
620 / 201 / 55
Регистрация: 27.02.2014
Сообщений: 1,067
#1

Десериализация разных классов с одним названием

02.02.2017, 16:09. Просмотров 858. Ответов 6
Метки нет (Все метки)

Проблема состоит вот в чем.

Изначально был выбран не слишком удачный способ сериализации, а именно BinarySerialization.
При использовании сериализации в c# генерируется информация о структуре класса.

Было два смежных проекта. Каждый из проектов имел класс, допустим, Data, который сериализовался и сохранялся в файл. Этот класс в разных проектах имеет разную структуру.

В какой-то момент возникло желание читать файлы обоих проектов в третьем проекте, что для данного типа сериализации само по себе, ИМХО, не предполагается.

Тем не меннее, если бы речь шла идет одном проекте, можно скопировать в него структуру сериализуемого класса.
Но, поскольку речь идет о двух разных классах с одинаковым именем, возникает конфликт.

Как это можно решить наиболее красиво?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.02.2017, 16:09
Ответы с готовыми решениями:

Десериализация классов наследников
Для теста имеется такой набор классов: public abstract...

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

Преобразоване классов из разных пространств имен
Добрый день! У меня существует два полностью одинаковых класса, но они...

Конфликт одноименных полей классов из разных Namespace
У меня есть задача следующего плана, Хотелось бы в ПО иметь несколько...

Сериализация и десериализация
Доброго вечера. Возникло странное непонимание принципов сериализации. Дело в...

6
1231231ghacking
97 / 101 / 62
Регистрация: 19.11.2015
Сообщений: 380
Завершенные тесты: 3
02.02.2017, 17:05 #2
Ты пробовал использовать разные namespace, а потом в аргументе, где нужно передавать тип сериализуемого объекта, передавать полное имя класса(namespace+Название класса)
0
OwenGlendower
Супер-модератор
Эксперт .NET
9045 / 7998 / 3418
Регистрация: 17.03.2014
Сообщений: 15,813
Записей в блоге: 1
02.02.2017, 18:17 #3
Mirmik, для этого можно использовать суррогаты сериализации. Правда код будет некрасивым т.к. нам придется заниматься ручной десереализацией класса.
сериализация
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
void Main()
{
    var test = new Test[] {
        new Test(45, "fhgfjgf"),
        new Test(53, "папавпва"),
        new Test(75575, "fhвавпывавgfjgf")
    };
    using (var fstream = File.Create("test.bin"))
    {
        var bf = new BinaryFormatter();
        bf.Serialize(fstream, test);
    }
}
 
[Serializable]
class Test
{
    private int x;
    private string s;
    
    public Test(int x, string s)
    {
        this.x = x;
        this.s = s;
    }
}

десереализация
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
void Main()
{
    using (var fstream = File.OpenRead("test.bin"))
    {
        var surrSel = new SurrogateSelector();
        surrSel.AddSurrogate(
            typeof(OtherTest),
            new StreamingContext(StreamingContextStates.All),
            new TestSurrogate()
        );
        var bf = new BinaryFormatter();
        bf.Binder = new TestBinder();
        bf.SurrogateSelector = surrSel;
        var t = (OtherTest[])bf.Deserialize(fstream);
    }
}
 
class TestSurrogate : ISerializationSurrogate
{
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        throw new NotImplementedException();
    }
    
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        OtherTest t = new OtherTest();
        t.X = info.GetInt32("x");
        t.S = info.GetString("s");
        return t;
    }
}
 
sealed class TestBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        if (typeName == "UserQuery+Test") return typeof(OtherTest);
        return Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
    }
}
 
[Serializable]
class OtherTest
{
    public int X;
    public string S;
}
0
insite2012
Модератор
Эксперт .NET
4849 / 3804 / 1094
Регистрация: 12.10.2013
Сообщений: 11,096
Записей в блоге: 2
02.02.2017, 18:34 #4
Цитата Сообщение от Mirmik Посмотреть сообщение
Как это можно решить наиболее красиво?
Использовать кроссдоменный/кросспроцессный/кроссплатформенный сериализатор (DataContractSerializer).
0
m0nax
1203 / 908 / 109
Регистрация: 12.01.2010
Сообщений: 1,891
Завершенные тесты: 3
02.02.2017, 21:12 #5
Лучший ответ Сообщение было отмечено Mirmik как решение

Решение

Можно использовать SerializationBinder со своими кастомными правилами
его BindToType принимает название типа как строку, возвращает Type
в каждом проекте делай свой со своими типами и всё
2
OwenGlendower
Супер-модератор
Эксперт .NET
9045 / 7998 / 3418
Регистрация: 17.03.2014
Сообщений: 15,813
Записей в блоге: 1
02.02.2017, 21:37 #6
Лучший ответ Сообщение было отмечено Mirmik как решение

Решение

m0nax, точно! Достаточно только SerializationBinder. Mirmik, вот исправленный пример уже без SerializationSurrogate
десериализация
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
void Main()
{
    using (var fstream = File.OpenRead("test.bin"))
    {
        var bf = new BinaryFormatter();
        bf.Binder = new TestBinder();
        var t = (OtherTest[])bf.Deserialize(fstream);
    }
}
 
sealed class TestBinder : SerializationBinder
{
    public override Type BindToType(string assemblyName, string typeName)
    {
        if (typeName == "UserQuery+Test") return typeof(OtherTest);
        return Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
    }
}
 
[Serializable]
class OtherTest
{
    private int x;
    private string s;
}
1
Mirmik
techpriest
620 / 201 / 55
Регистрация: 27.02.2014
Сообщений: 1,067
03.02.2017, 10:30  [ТС] #7
Отлично. И на основе дополнительной информации о природе файла (например, если расширение разное, как в моем случае, передавать его биндеру в конструкторе) можно подсовывать либо один, либо другой тип, даже если на входе имеем одно и тоже название типа и сборки...

Спасибо .
0
03.02.2017, 10:30
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.02.2017, 10:30

Десериализация в List
Здравствуйте. Есть следующий код : using System; using...

Десериализация JSON
Есть данные от известного источника в JSON: {"response":} При помощи...

Десериализация XML
Пытаюсь десереализировать XML структуру, но или получаю неверное соответствие...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru