Почему вы не можете поместить виртуальный метод GetViewModel()
в базовый класс PageItem, который возвращает подходящую модель представления?
foreach (PageItem pageItem in pageItems)
{
pageItemViewModels.Add(pageItem.GetViewModel());
}
То, что сразу выглядит как запах кода, это использование свойств "id" - обычно его можно заменить полиморфизмом. Таким образом, вы должны заменить оператор switch
на приведенный выше код.
Edit:
Если ваш класс PageItem ничего не знает о вашей модели представления, то он не может быть реализован таким образом. По сути, вам нужен завод, который у вас уже есть (в некотором смысле).
У меня обычно есть список отношений (PageItem к ViewModel), который в вашем случае будет Dictionary<String, Type>
. Затем вы можете заполнить этот список во время инициализации и создать соответствующую модель представления позже.
Чтобы использовать отражение для построения этого списка, вам по крайней мере необходимо программно знать, какой элемент страницы поддерживается моделью представления. Для этого вы можете использовать собственный атрибут для украшения вашего класса, например ::
public class SupportsPageItemAttribute : Attribute
{
private readonly string _id;
public string ID
{
get { return _id;}
}
public SupportsPageItemAttribute(string id)
{
_id = id;
}
}
А затем используйте этот атрибут, чтобы определить, какой PageItem может принять ваша модель:
[SupportsPageItemAttribute("manageCustomers")
public class PageItemManageCustomersViewModel
{
// ...
}
И затем вы используете отражение, чтобы получить все классы, реализующие IPageItemViewModel, и проверить их атрибуты, чтобы получить строку идентификатора PageItem.
Например (без особой проверки ошибок):
Dictionary<String, Type> modelsById = new Dictionary<String, Type>();
String viewModelInterface = typeof(IPageItemViewModel).FullName;
// get the assembly
Assembly assembly = Assembly.GetAssembly(typeof(IPageItemViewModel));
// iterate through all types
foreach (Type viewModel in assembly.GetTypes())
{
// get classes which implement IPageItemViewModel
if (viewModel.GetInterface(viewModelInterface) != null)
{
// get the attribute we're interested in
foreach (Attribute att in Attribute.GetCustomAttributes(viewModel))
{
if (att is SupportsPageItemAttribute)
{
// get the page item id
String id = (att as SupportsPageItemAttribute).ID;
// add to dictionary
modelsById.Add(id, viewModel);
}
}
}
}
С другой стороны, существуют различные структуры инверсии контроля, которые вы могли бы рассмотреть вместо того, чтобы самостоятельно выполнять неприятную работу по отражению.