Привет. Столкнулся с проблемой в написании кода и решил спросить совета у коллег. Заодно решил проверить, всесилен ли пикабу? (Надеюсь, что да). Поэтому проблему решил излить не в специализированном форуме, а здесь - на развлекательном ресурсе. Посмотрим, что из этого выйдет.
Проблема в синтаксисе языка C#. Имеется функция, которая принимает на выполнение некую коллекцию. В зависимости от типа объектов в коллекциии, она должна инициировать определенный менеджер и выполнить операцию.
Операции предельно одинаковые, но реализация этой операции в рамках менеджера сильно сильно отличается. Поэтому функция должна быть одна, но вызывать разные классы с общим родителем.
Теперь приведу код для примера. Конечно сильно упрощенный:
Опишем структуру данных
//Объекты Дом, Улица, Город. Для примера они пустые. Но и так понятно, что там может быть
public class BaseObject { }
public class House:BaseObject { }
public class Street : BaseObject { }
public class City : BaseObject { }
//Базовый класс набора менеджеров
public class BaseManager<T>
{
public virtual void Export(T objectToExport) { }
}
//Менеджер для операции экспорта домов
public class HouseManager:BaseManager<House>
{
public override void Export(House objectToExport)
{
//Что - то делаем для экспорта
}
}
//Менеджер для операции экспорта улиц
public class StreetManager : BaseManager<Street>
{
public override void Export(Street objectToExport)
{
//Что - то делаем для экспорта
}
}
//Менеджер для операции экспорта городов
public class CityManager : BaseManager<City>
{
public override void Export(City objectToExport)
{
//Что - то делаем для экспорта
}
}
Собственно макет некой функции, которая выполняет логику:
public void DoExport(List<BaseObject> exportCollection)
{
BaseManager<T> manager = null;//Как мне этот менеджер объявить?
if (exportCollection[0].GetType() == typeof(House))
{
manager = new HouseManager();
}
else if (exportCollection[0].GetType() == typeof(Street))
{
manager = new StreetManager();
}
else
{
manager = new CityManager();
}
//Пробежимся по всем объектам коллекции и вызовем операцию экспорта
foreach (BaseObject item in exportCollection)
{
manager.Export(item);
}
}
Эта функция будет окрашена красным и не скомпиллируется. Т.к. я ума не приложу, как красиво задекларировать переменную manager
var manager = null; не катит. Т.к. требуется инициализация.
var manager = new HouseManager(); пропустит, но на этапе преобразование в блоке условий не даст собрать приложение.
Выход был найден, если объявить этот менеджер так:
dynamic manager = null;
Тогда все работает как надо. Но имеется огромный минус. Полностью пропадает контроль над кодом. Изменения в классах никак не отследить на этапе сборки. Только ловя исключения.
А если учесть, что реальная программа много сложнее, является службой с поддержкой многопоточного выполнения операций, то это не лучшее решение. Но пока единственное.
Прошу знающих людей помочь советом. Чувствую, что как - то можно это все сделать. И где - то я торможу.