1 / 1 / 0
Регистрация: 13.05.2014
Сообщений: 66
1

Сериализация в Json экземпляра интерфейса

30.05.2016, 11:55. Показов 3994. Ответов 26
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть два класса, которые были наследование от интерфейса и класс в котором объявлена переменная типа интерфейса от которого наследуются два предыдущих класса.
Сделано это было ля того, что бы можно было передавать разные по структуре классы классы.
Думаю суть и логику вы уловили, буду благодарен за любую инфу.
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
interface SomeInterface
{
}
class class1 : SomeInterface
{
   public string str1;
   public string str2;
   public string str3;
   public string str4;
}
class class2 : SomeInterface
{
   public int int1;
   public int int2;
   public int int3;
   public int int4;
}
 
class SomeClass
{
    public string strInfo;
    public SomeInterface SomeInterface1;
}
 
private void Method1()
{
    class1 cl = new class1{ str1 = "1", str1 = "2", str1 = "3", str1 = "4"};
    SomeClass sc = new SomeClass
    {
        strInfo = "123", SomeInterface1 = cl
    };
    string s =  Newtonsoft.Json.JsonConvert.SerializeObject(sc);
}
Естественно вылетает исключение которое пытается сказать что нельзя делать так с интерфейсами.
Вопрос: можно ли каким - то образом передавать разные классы через одну и ту же переменную?

Добавлено через 11 часов 45 минут
Это хотя бы возможно?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.05.2016, 11:55
Ответы с готовыми решениями:

Сериализация интерфейса
здравствуйте. такое дело - у меня есть интерфейс (Interface) и от него наследуются два класса...

Сериализация экземпляра типа FileInfo
Здравствуйте!Есть у меня необходимость записать в файл класс fileinfo а потом вычитать его...

Создание экземпляра интерфейса Microsoft.Office.Interop.Excel
Добр. день Если сделать это: using Excel = Microsoft.Office.Interop.Excel;...

Сериализация в JSON
Добрый день. Прошерстил доки по сериализации JSON, нагугли несколько библиотек, но так и не смог...

26
447 / 300 / 65
Регистрация: 12.10.2009
Сообщений: 1,162
30.05.2016, 13:01 2
Лучший ответ Сообщение было отмечено turissssst как решение

Решение

сериализация/десериализация экземпляров интерфейсов не допустима архитектурой C#.
1) интерфейсы - (в терминах С++) чистые абстрактные виртуальные классы по этому смотрим пункт 2
2) нельзя создать экземпляр интерфейса
3) значит под интерфейс можно спрятать только "наследника" такого интерфейса
4) при сериализации библиотека Json .NET знает какие экземпляры каких классов она превращает в json
5) при десереализации json обратно в экземпляр класса эта информация теряется
6) поэтому без сохранения информации о типах инициализация экземпляров интерфейсов не возможна
7) т. к. информация о типах в виде json занимает много места и зачастую бесполезна то общий вывод таков
8) НЕ СЕРИАЛИЗУЙТЕ ИНТЕРФЕЙСЫ!!!


для хранения разных экземпляров классов одной иерархии наследования в одной переменной используй базовые классы этой иерархии

вот тебе код для анализа

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 Newtonsoft.Json;
 
namespace ConsoleApplication1
{
 
    public interface ISomeInterface<T1,T2,T3,T4>
    {
        T1 element1 { get; set; }
        T2 element2 { get; set; }
        T3 element3 { get; set; }
        T4 element4 { get; set; }
        void PrintType();
    }
 
    public class BaseClassForSomeInterface<T1, T2, T3, T4> : ISomeInterface<T1, T2, T3, T4>
    {
        public T1 element1 { get; set; }
        public T2 element2 { get; set; }
        public T3 element3 { get; set; }
        public T4 element4 { get; set; }
 
        public virtual void PrintType()
        {
            Console.WriteLine($"this type class: {GetType()}");
        }
    }
 
    public class Class1 : BaseClassForSomeInterface<string,string,string,string>
    {
        public override void PrintType()
        {
            Console.WriteLine("this type class: class1");
        }
    }
    public class Class2 : BaseClassForSomeInterface<int,int,int,int>
    {
        public override void PrintType()
        {
            Console.WriteLine("this type class: class2");
        }
    }
 
    public class SomeClass
    {
        public string strInfo;
        public ISomeInterface<string, string, string, string> ClassInstance1 { get; set; }
        public ISomeInterface<int, int, int, int> ClassInstance2 { get; set; }
 
        public void PrintType()
        {
            Console.WriteLine("this type class: SomeClass");
            ClassInstance1.PrintType();
            ClassInstance2.PrintType();
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            var instance = new SomeClass
            {
                strInfo = "123",
                ClassInstance1 = new Class1 { element1 = "1", element2 = "2", element3 = "3", element4 = "4" },
                ClassInstance2 = new Class2 { element1 = 1, element2 = 2, element3 = 3, element4 = 4 }
            };
            PrintInstanceType(instance, "instance");
            var jsonSerializerSettings = new JsonSerializerSettings()
            {
                TypeNameHandling = TypeNameHandling.All
            };
            var json1 = JsonConvert.SerializeObject(instance);
            var json2 = JsonConvert.SerializeObject(instance, jsonSerializerSettings);
            try
            {
                var jsonResult1 = JsonConvert.DeserializeObject<SomeClass>(json1);
                PrintInstanceType(jsonResult1, "jsonResult1");
            }
            catch (Exception exception)
            {
                Console.WriteLine($"instance class: jsonResult1");
                Console.WriteLine("Deserialization Exception!!!");
                Console.WriteLine();
            }
            var jsonResult2 = JsonConvert.DeserializeObject<SomeClass>(json2, jsonSerializerSettings);
            PrintInstanceType(jsonResult2, "jsonResult2");
            Console.WriteLine("Press any key for exit...");
            Console.ReadKey(true);
        }
 
        private static void PrintInstanceType(SomeClass instance, string name)
        {
            Console.WriteLine($"instance class: {name}");
            instance.PrintType();
            Console.WriteLine();
        }
    }
}
1
1 / 1 / 0
Регистрация: 13.05.2014
Сообщений: 66
30.05.2016, 19:10  [ТС] 3
Делаю я это для передачи сообщений через сокеты на сервер.
Может есть иной способ передачи данных, который лучше подойдет под это дела?
0
447 / 300 / 65
Регистрация: 12.10.2009
Сообщений: 1,162
31.05.2016, 13:36 4
WCF + net.tcp слышал о таком?

Добавлено через 41 секунду
а сокеты это очень специфичная область, пока туда не лезь
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 13:39 5
Цитата Сообщение от turissssst Посмотреть сообщение
Делаю я это для передачи сообщений через сокеты на сервер.
Выше ужа сказано, WCF+нужный транспорт+контракты данных с необходимыми свойствами. И DataContractSerializer сам их сериализует-десериализует, без вашего участия (или с минимальным).
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 14:43 6
агерон, insite2012, боюсь, у ТС возникнет таже-самая проблема и на WCF, поскольку перейдя с Socket на WCF поменяется только транспорт. Попытки передать интерфейс останутся.
turissssst, приложения с обоих концов канала связи УЖЕ должны знать этот интерфейс для правильной сериализации/десериализации (хотя я видел людей которые десериализовывали данные в dynamic и вытаскивали из него данные, которые там подразумеваются).
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 15:21 7
Цитата Сообщение от aquaMakc Посмотреть сообщение
Попытки передать интерфейс останутся.
Насколько я знаю, WCF это допускает (использование интерфейсов в параметрах/возвращаемых значениях операций). Там не без нюансов (куда же без них), но это возможно.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 15:24 8
Цитата Сообщение от insite2012 Посмотреть сообщение
Насколько я знаю, WCF это допускает
Сдаётся мне, не сам интерфейс можно передавать, а его реализацию, но опять-же, для этого программы с обоих концов должны понимать этот интерфейс.
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 15:29 9
Цитата Сообщение от aquaMakc Посмотреть сообщение
Сдаётся мне, не сам интерфейс можно передавать
Естественно, в месте вызова будет использован фактический тип. Но в параметре будет интерфейс. Ну и атрибут ServiceKnownType понадобится. Джувел Леве, стр.112.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 15:35 10
Цитата Сообщение от insite2012 Посмотреть сообщение
Естественно, в месте вызова будет использован фактический тип. Но в параметре будет интерфейс.
Вот только не вижу смысла. Передавать реализацию интерфейса с методами - не уверен, что можно, об этом ничего не написано, а для передачи объекта только со свойствами лучше использовать DataContract.
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 16:57 11
Цитата Сообщение от aquaMakc Посмотреть сообщение
Передавать реализацию интерфейса с методами - не уверен, что можно, об этом ничего не написано
Ну как не написано. Ясно сказано, что логика не передается, а только данные. Но разговор шел про интерфейсы, а в них вполне могут присутствовать и свойства, не так ли? Или свойства уже не данные?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 16:58 12
Цитата Сообщение от insite2012 Посмотреть сообщение
Но разговор шел про интерфейсы, а в них вполне могут присутствовать и свойства, не так ли? Или свойства уже не данные?
Цитата Сообщение от aquaMakc Посмотреть сообщение
а для передачи объекта только со свойствами лучше использовать DataContract.
) внимательней
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 17:14 13
Цитата Сообщение от aquaMakc Посмотреть сообщение
внимательней
Ну так.
DataContract сам по себе не передается. Это атрибут, от только декорирует тип (которым вполне может быть и интерфейс), указывая, что этот тип может использоваться как контракт данных.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 17:21 14
Цитата Сообщение от insite2012 Посмотреть сообщение
DataContract сам по себе не передается. Это атрибут, от только декорирует тип (которым вполне может быть и интерфейс), указывая, что этот тип может использоваться как контракт данных.
Я к тому, что не вижу принципиальной необходимости передавать объект, наследованный от интерфейса, как контейнер с данными, если можно отправить DataContract, как тот-же самый контейнер, но совершив для этого меньше действий.
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 17:23 15
Цитата Сообщение от aquaMakc Посмотреть сообщение
не вижу принципиальной необходимости передавать объект, наследованный от интерфейса
А как же полиморфизм?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 17:29 16
Цитата Сообщение от insite2012 Посмотреть сообщение
А как же полиморфизм?
) полиморфизм чего? свойств? тип свойства строго определён в любом случае, содержимое их, так-же в любом случае определяет отправитель.
Подключи с обеих сторон программы dll`ку с DataContract`ом и необходимость интерфейса (который также должен быть с обеих сторон), как "прокрустово ложе" передаваемых данных отпадает.
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 17:36 17
Цитата Сообщение от aquaMakc Посмотреть сообщение
полиморфизм чего? свойств?
Каких свойств??? Вы что, никогда не использовали интерфейсы? Не знаете как их использовать?
Цитата Сообщение от aquaMakc Посмотреть сообщение
необходимость интерфейса (который также должен быть с обеих сторон), как "прокрустово ложе" передаваемых данных отпадает.
С чего бы? Еще раз говорю, интерфейсы вполне допустимо использовать (а иногда это нужно).
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 17:52 18
Цитата Сообщение от insite2012 Посмотреть сообщение
Каких свойств??? Вы что, никогда не использовали интерфейсы? Не знаете как их использовать?
Цитата Сообщение от insite2012 Посмотреть сообщение
Ну как не написано. Ясно сказано, что логика не передается, а только данные. Но разговор шел про интерфейсы, а в них вполне могут присутствовать и свойства, не так ли?
есть интерфейс
C#
1
2
3
4
5
interface iMyInterface
{
    int MyInt{get;}
    string MyString {get;}
}
и его реализация
C#
1
2
3
4
5
6
7
8
class TMyClass : iMyInterface
{
    int _MyInt = 0;
    string _MyString = "АБЫР";
 
    int MyInt{get {return _MyInt ;}}
    string MyString {get {return _MyString ;}}
}
и есть

C#
1
2
3
4
5
6
7
8
class TMyClass1 : iMyInterface
{
    int _MyInt = 100500;
    string _MyString = "Hello World";
 
    int MyInt{get {return _MyInt + 1 ;}}
    string MyString {get {return _MyString.Replace("A", "B");}}
}
это полиморфизм, но нужно ли оно нам, если мы можем написать
C#
1
2
3
4
5
6
7
8
9
    [DataContract]
    public class TWcfData
    {
        [DataMember]
        public int MyInt { get; set; }
 
        [DataMember]
        public string MyString { get; set; }
    }
заполнить его нужными данными и передать.

Добавлено через 6 минут
) public`ки забыл
0
Эксперт .NET
5531 / 4296 / 1216
Регистрация: 12.10.2013
Сообщений: 12,329
Записей в блоге: 2
31.05.2016, 17:56 19
Цитата Сообщение от aquaMakc Посмотреть сообщение
это полиморфизм, но нужно ли оно нам, если мы можем написать
Можно. Но если есть несколько типов, общих с этим интерфейсом, то почему бы нам не передать в параметре именно его? Или плодить 100500 методов на каждый тип?
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
31.05.2016, 17:59 20
Цитата Сообщение от insite2012 Посмотреть сообщение
Но если есть несколько типов, общих с этим интерфейсом, то почему бы нам не передать в параметре именно его? Или плодить 100500 методов на каждый тип?
Интерфейс предусматривает строгое соблюдение сигнатуры. Если у нас для каждого метода разный набор данных - придётся плодить зоопарк интерфейсов, если набор данных одинаковый можно обойтись одним DataContract`ом, создавая по экземпляру на каждый метод.
0
31.05.2016, 17:59
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.05.2016, 17:59
Помогаю со студенческими работами здесь

Сериализация JSON
Привет! Прошу помощи, не могу понять, как собрать Json обратно. В общем изначально я получаю данные...

Сериализация JSON
Здравствуйте! Допустим есть класс: public class Point2D { public double X, Y; private...

Сериализация JSON
Подскажите дураку как создать следующий JSON средствами QJsonArray QJsonObject QJsonDoument...

Сериализация JSON в C#
Доброго времени суток! Начал изучать сериализацию JSON и возникли некоторые недопонимания с моей...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru