Мы унаследовали проект, который является оболочкой для части основной бизнес-модели.
Есть один метод, который берет универсальный, находит элементы, соответствующие этому типу, от члена, а затем возвращает список этого типа.
public List<T> GetFoos<T>()
{
List<IFoo> matches = Foos.FindAll(
f => f.GetType() == typeof(T)
);
List<T> resultList = new List<T>();
foreach (var match in matches)
{
resultList.Add((T)obj);
}
}
Foos может содержать один и тот же объект, приведенный к различным классам в иерархии наследования, чтобы по-разному агрегировать итоги для разных представлений пользовательского интерфейса. Существует более 20 различных типов потомков, которые могут быть возвращены GetFoos.
Существующий код в основном имеет большой оператор switch, скопированный и вставленный в код. Код в каждом разделе вызывает GetFoos с соответствующим ему типом.
В настоящее время мы проводим рефакторинг этого в одну консолидированную область, но пока мы делаем это, мы ищем другие способы работы с этим методом.
Одна мысль состояла в том, чтобы использовать отражение для передачи типа, и это прекрасно работало, пока мы не осознали, что Invoke вернул объект, и что его нужно как-то привести к списку .
Другой вариант - просто использовать оператор switch до 4.0, а затем использовать параметры динамического языка.
Мы приветствуем любые альтернативные мысли о том, как мы можем работать с этим методом. Я оставил код довольно кратким, но если вы хотите узнать какие-либо дополнительные детали, просто спросите.
Обновление
Оператор switch изначально использовал строки, и при первом проходе он перемещался в Presenter примерно так: (На коммутаторе не выполнялся рефакторинг, только куда делись данные).
// called on an event handler in FooPresenter
// view is the interface for the ASPX page injected into FooPresenter's constructor
// wrapper is the instance of the model wrapper that has the GetFoos method
// selectedFooName is the value of a DropDownList in the Page
// letting the user say how they want to see the animals
// its either one big group (Animal)
// or individual types (Tiger, Lion)
private void LoadFoos(string selectedFooName)
{
switch (selectedFooName)
{
case "Animal": // abstract base class for all other types
this.view.SetData(this.wrapper.GetFoos<Animal>();
case "Lion":
this.view.SetData(this.wrapper.GetFoos<Lion>();
break;
case "Tiger":
this.view.SetData(this.wrapper.GetFoos<Tiger>();
break;
case "Bear":
this.view.SetData(this.wrapper.GetFoos<Bear>();
break;
}
}
Реализация View (код для страницы ASPX)
public void SetData<T>(List<T> data)
{
// there is a multiview on the page that contains user controls with
// grid layouts for the different types
// there is a control for the common type of "Animal"
// and other controls for Tiger, Bear, etc
// the controls contain a 3rd party grid of pain
// and the grids' binding event handlers cast the data item
// for the row and do some stuff with it specific to that type
}
Нашим первым проходом было как минимум использование Type в операторе switch или добавление enum.
Я поэкспериментировал с использованием паттерна стратегии, но мне пришлось остановиться, когда я вернулся на фабрику загрузки, снова вернув Список и поняв, что у меня нет этого типа.