#c# #design-patterns #types #specialization
#c# #шаблоны проектирования #типы #специализация
Вопрос:
Представьте, что у меня есть общий класс Person
. Тогда у меня есть специализации этого класса, например DanishPerson
и BritishPerson
.
Теперь мне нужна функция, которая возвращает правильный экземпляр Persons, в зависимости от того, в какой стране они находятся, или способ легко определить, к какому типу людей они относятся. Итак, у меня есть функция:
List<Person> GetPersonsByCountry(int countryId)
{
// query database, and get list of Persons in that country using EF inheritance
// return list of persons
}
Список лиц содержит объекты, которые либо имеют тип DanishPerson
, либо BritishPerson
. В зависимости от типа мне нужно отобразить правильную ViewModel в моем пользовательском интерфейсе. Итак, если список содержит датских пользователей типа DanishPerson
, мне нужно отобразить один пользовательский интерфейс, который будет отображать свойства, специфичные для датского языка (и многое другое).
Теперь мой вопрос в том, как вы делаете это наилучшим образом? Я думаю, что я всегда мог бы использовать if / else с помощью typeof
, но я надеялся на более элегантный и, возможно, универсальный способ? Я подумал, что для этого могут быть какие-то шаблоны, поскольку мне кажется, что это обычная проблема при работе со специализациями?
Ответ №1:
Вы могли бы использовать a Dictionary<K, V>
для хранения сопоставлений между кодами стран и связанным типом класса, а затем использовать метод LINQ OfType
для получения только экземпляров типа, связанного с предоставленным кодом страны.
Ответ №2:
Вы можете использовать словарь для отображения поведения в соответствии с типом пользователя. Еще лучше создать интерфейс Ibehaviour и унаследовать от него два класса, один для британского и один для датского, и инкапсулировать различное поведение между ними.
При добавлении другого типа person требуется создание класса behavior и обновление словаря.
Создайте словарь (закрытый член класса):
Dictionary<Type, IBehaviour> mapper = new Dictionary<Type, IBehaviour>()
{
{typeof(BritishPerson), new BritishPersonBehaviour()},
{typeof(DanishPerson), new DanishPersonBehaviour()}
};
В коде:
Person person = ...
var behaviour = mapper[person.GetType()];
behaviour.ShowUI(); //or something like this
Комментарии:
1. Спасибо, Дрор. Можете ли вы привести мне краткий пример реализации? Или, может быть, вы знаете статью, описывающую это?
2. Большое вам спасибо. Это кажется хорошим решением, и я бы попробовал его реализовать. Знаете ли вы другие способы сделать это, о которых я должен знать?
Ответ №3:
Если объект List однороден (т. е. он всегда заполнен только датскими или британскими объектами person, то этот маленький кусочек LINQ сработает:
var list = GetPersonsByCountry(1);
if (list.OfType<BritishPerson>().Any())
ShowBritishUI();
else
ShowDanishUI();