Нужна ли обертка над моделями представления для управления вложенностями и как управлять вложенностями в части сериализации и десериализации
Есть классы VM:
public class SyllabusVM
{
public string TitleSyllabus { get; set; } = string.Empty;
public List<SemestrVM>? Semesters { get; set; }
}
public class SemestrVM
{
public int Number { get; set; }
public List<DisciplineVM>? DisciplineS { get; set; }
}
public class DisciplineVM
{
public string Subject { get; set; } = string.Empty;
public int HoursLecture { get; set; }
public int HoursPractice { get; set; }
public string TypeOfControl { get; set; } = string.Empty;
}
И для VM классы Model:
public class SyllabusModel
{
public string TitleSyllabus { get; set; } = string.Empty;
public List<SemestrModel>? Semesters { get; set; }
}
public class SemestrModel
{
public int Number { get; set; }
public List<DisciplineModel>? DisciplineS { get; set; }
}
public class DisciplineModel
{
public string Subject { get; set; } = string.Empty;
public int HoursLecture { get; set; }
public int HoursPractice { get; set; }
public string TypeOfControl { get; set; } = string.Empty;
}
Мне нужно будет управлять списками внутри каждой вложенности (добавлять, удалять и изменять), а также сериализовать и десериализовать для этого правильно ли я понимаю что надо:
- В выше описанных VM я не создаю команды и логику по управлению списками и сериализацией\десериализацией, а создаю отдельную ViewModel в которой имеется бизнес логика над VM описанных выше - т.е. обертка.
Пример:
public class SyllabusViewModel : ReactiveObject
{
public ReactiveCommand<Unit,Unit> CreateSyllabucCommand { get; set; }
public ReactiveCommand<Unit,Unit> EditSyllabucCommand { get; set; }
public ReactiveCommand<Unit,Unit> DeleteSyllabucCommand { get; set; }
public ObservableCollection<SyllabusVM> Curriculum { get; set; }
public SyllabusViewModel()
{
Curriculum = new ObservableCollection<SyllabusVM>();
//МАПИНГ
foreach (var syllabus in serviceData.GetDataSyllabus())
Curriculum.Add(syllabus);
//МАПИНГ
CreateSyllabucCommand = ReactiveCommand.Create(CreateSyllabus);
EditSyllabucCommand = ReactiveCommand.Create(EditeSyllabus);
DeleteSyllabucCommand = ReactiveCommand.Create(DeleteSyllabus);
}
void CreateSyllabus() { }
void EditeSyllabus() { }
void DeleteSyllabus() { }
}
И такие ViewModel - обертки для каждой VM описанной выше. Нужны ли эти обертки или эта логика должна быть в VM описанных выше???
Как правильно сериализовать такую вложенность. Зайти через верхний уровень и пройтись по каждой вложенностb через foreach-foreach-foreach и замапить типы VM в Model и сериализовать. Или же каждый слой сам должен делать мапинг. Или же может что-то другое дайте понимание сериализации вложенности с мапингом если он нужен)).
Каждый учебный план представляет собой Json файл, который в сервисе засовывается в ICollection, мапиться в SyllabusVM и возвращается в
public ObservableCollection<SyllabusVM> Curriculum { get; set; }.
Нужен ли такой мапинг в каждой прослойке для своего списка или же мапинг должен быть только на самом верхнем уровне вложенности пройдя по всей вложенностями несколькими циклами foreach-foreach-foreach???
Подскажите, пожалуйста)))
Ответы (1 шт):
Пожалей читающих... от SyllabusVM.TitleSyllabus
глаза выкатываются с свистом, контекст хуже некуда. Не обязательно писать Model
в имени, это и так понятно по объекту, без бизнес логики и каких либо других ключевых слов в имени.
для VM классы Model
Не модели существуют для представлений, а представления для моделей. И когда пишут для
это указывает на отношение одного к другому, но у тебя *VM
никак ни к чему не относится, это просто тупо бесталковый клоны *Model
, хотя должен быть его обёрткой.
ViewModel - обертки для VM
Извиняюсь за не скромный вопрос, а VM
это не сокращение ViewModel
? Взаимодействовать с одним или набором нескольких ViewModel
, задача View
!
Тут нет такого понятия как вложенность
, это не разметка, не может один объект (например дисциплина) быть вложен в несколько других (семестры), на него могут только ссылаться объект (несколько семестров ссылаются на одну и ту-же дисциплину). Это называется отношения/связь (eng:relation), а базы данных с связанными данными, называются реляционными
(Relational
).
Какую функцию у тебя выполняет ViewModel
? ViewModel
это обёртка над Model
. Например, если в Model
есть url
изображения, то в ViewModel
может находиться загруженный по этой ссылке byte[]
изображения, что бы его можно было отобразить в View
. Одна ViewModel
может и вовсе быть продуктом сразу нескольких Model
. ViewModel
это только посредник, не содержащий значимых данных, в нём нечего сериализовывать и в теме сохраниния данных он не участвует, от слова "ваще".
Ты столкнулся с проблемой, что если на дисциплину ссылаются несколько семестров, то при сериализации/десиаризации, семестры начинают ссылаться на разные копии одной и той-же дисциплины, потому что не сохраняются отношения между ними, только структура и значения.
Как Model
не знает о существовании View
, который её отображает, так он не должен знать о существовании сохранении/загрузки. Сохранение/загрузка это логика, которую всегда описывают отдельно, она не находится ни в модели, ни в представлении, ни в чём, она сама по себе. Как ViewModel
посредник для View
, так-же может быть посредник для хранения данных.
public class Discipline
{
public string Name { get; set; } = string.Empty;
...
}
public class Semestr
{
public int Number { get; set; }
[JsonIgnore]
public List<Discipline> Disciplines { get; set; }
}
public class SemestrData
{
public Semestr Semestr { get; set; }
public IEnumerable<string> DisciplineNames { get; set; }
public SemestrData (Semestr semestr)
{
Semestr = semestr;
DisciplineNames = Semestr.Disciplines.Select(s => s.Name);
}
}
SemestrData
легко сериализуется в Json
не имея никаких ссылок, а только имена дисциплин.
public class LernData
{
public SyllabusData SyllabuData { get; set; }
public IEnumerable<SemestrData> SemestrData { get; set; }
public IEnumerable<Discipline> Disciplines { get; set; }
}
Сам LernData
сериализуется в Json
и является контейнером набора взаимозависимых данных, сохраняющего целостность.
public void LinkData (LernData data)
{
LinkSyllabusWithSemestrs(data.SyllabuData, data.SemestrData);
LinkSemestrsWithDisciplines(data.SemestrData, data.Disciplines);
}
private void LinkSemestrsWithDisciplines (IEnumerable<SemestrData> semestrDatam, IEnumerable<Discipline> disciplines)
{
Dictionary<string, Discipline> dDisciplines = disciplines.ToDictionary(d => d.Name);
foreach (var data in semestrData)
{
List<Discipline> sDisciplines = new List<Discipline>();
foreach (string name in data.DisciplineNames)
sDisciplines.Add(dDisciplines[name]);
data.Semestr.Disciplines = sDisciplines;
}
}
Нужен только класс, которому скармливаешь план, семестры и дисциплины для дальнейшей упаковки в обёртки и контейнер LernData
и его сериализации, а так-же десириализации с дальнейшим восстановлением связей между сущьностями по данным в обёртке.