Я немного запутался в паттерне MVVM, который я комбинирую с PRISM.Вкратце: я пытаюсь создать представления и модели представления на основе существующих моделей, которые создаются отдельным сервисом.Сервис не знает и не должен ничего знать о видах и / или моделях видов.Этот сервис создает модели разных типов, для простоты давайте назовем их SquareModel и CircleModel.Все эти типы имеют одну и ту же абстрактную BaseModel.Предположим, что служба генерирует список типа BaseModel с квадратными и круговыми моделями.Теперь вопрос в том, как я перевожу эти Модели в соответствующие ViewModels и помещаю их в новый список.Каждый тип должен иметь свою собственную модель представления;так:
- SquareModel -> SquareViewModel
- CircleModel -> CircleViewModel
Это связано с тем, что обе модели предоставляют разные свойства, которые я хочу связать с помощьюViewModel.Кроме того, как мне объединить эти два типа ViewModel в один список для представления моему представлению?
Представление содержит список, который в зависимости от типа представления загружает соответствующий шаблон данных.
Для созданиявсе более понятно, я собрал пример кода, показанного ниже, чтобы показать, что я сделал.Первый подход - через переключение типа, второй - использование ExportFactory из MEF 2.0.И то, и другое терпит неудачу, причина в коде.Я действительно ценю любую помощь!
/*
* Models (these are generated by a service, the service doesn't and should not now about views or view models)
*
*
*/
abstract class BaseModel { }
class SquareModel : BaseModel { }
class CircleModel : BaseModel { }
/*
* View Models
*
*
*/
abstract class BaseViewModel<TModel> // : INOtificationPropertyChanged, etc
{
protected TModel Model;
public void SetModel(TModel model)
{
Model = model;
OnChangeModel();
}
protected virtual void OnChangeModel()
{
// Assignment of base properties here, based on Model
}
// Declarate some base properties here
}
[Export(typeof(BaseViewModel<BaseModel>))]
[TypeMetadata(Type = "CircleViewModel")]
class CircleViewModel : BaseViewModel<CircleModel>
{
protected override void OnChangeModel()
{
// Assignment of circle specific properties here, based on Model
}
// Declarate some circle specific properties here
}
[Export(typeof(BaseViewModel<BaseModel>))]
[TypeMetadata(Type = "SquareViewModel")]
class SquareViewModel : BaseViewModel<SquareModel>
{
protected override void OnChangeModel()
{
// Assignment of square specific properties here, based on Model
}
// Declarate some square specific properties here
}
class Program
{
[ImportMany]
protected IEnumerable<ExportFactory<BaseViewModel<BaseModel>, ITypeMetadata>> Factories { get; set; }
public BaseViewModel<BaseModel> Create(string viewModelType)
{
var factory = (from f in Factories where f.Metadata.Type.Equals(viewModelType) select f).First();
// Factory is able to create View Models of type viewModelType using CreateExport() function
var vm = factory.CreateExport().Value;
return vm;
// Same error as with solution A
// cannot convert from 'ConsoleApplication1.SquareViewModel' to 'ConsoleApplication1.BaseViewModel<ConsoleApplication1.BaseModel>'
// This error is actually displayed in ExportFactory context, but it means the same
}
public BaseViewModel<BaseModel> CreateFrom(Type type)
{
var vmTypeName = type.Name + "ViewModel";
return Create(vmTypeName);
}
public BaseViewModel<BaseModel> CreateVMUsingExportFactory(BaseModel model)
{
var vm = CreateFrom(model.GetType());
vm.SetModel(model);
return vm;
}
public void DoStuff()
{
// Suppose service gives me this
var serviceOutput = new List<BaseModel>
{
new SquareModel(),
new CircleModel(),
new CircleModel(),
new SquareModel(),
new CircleModel(),
new SquareModel(),
new SquareModel()
// may be longer but not the point
};
// viewModelCollection is bound to a listbox, by using datatemplates everthing is nicely placed on the canvas; no problem there
// Actually this is a ObserveableCollection
List<BaseViewModel<BaseModel>> viewModelCollection = new List<BaseViewModel<BaseModel>>();
//
// What to do here?
//
//
// A. Switch-on-type
foreach (var model in serviceOutput)
{
// Note there are beter implementations of this, using dicationaries and delegates, main goal of that is to not break when refactoring;
switch (model.GetType().Name)
{
case "SquareModel":
SquareViewModel vm = new SquareViewModel();
vm.SetModel((SquareModel)model); // another cast..... :(
viewModelCollection.Add(vm);
// Error:
// cannot convert from 'ConsoleApplication1.SquareViewModel' to 'ConsoleApplication1.BaseViewModel<ConsoleApplication1.BaseModel>'
break;
case "CircleModel":
// same
break;
}
}
// B. MEF ExportFactory<>
//
foreach (var model in serviceOutput)
{
var vm = CreateVMUsingExportFactory(model);
viewModelCollection.Add(vm);
}
// C. Something else?!
//
// Please help ;-).
}
a