Специализация типов; как определить и реагировать на каждый конкретный тип?

#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();