In our project we are using .net WPF with MEF and prism. I have to do some task and as a part of it I have different classes of Model, all implementing IModel interface (let's call them Model1, Model2, Model3). For each model class I need to create a view model (ViewModel1, ViewModel2, ViewModel3). I would like to do it in some generic way so it will be extensible and if tomorrow someone will implement IModel in different dll that I doesn't know about, I still will be able to create a view model for it.
I though about something like this:
[InheritedExport]
public interface IViewModelFactory<T>
{
IViewModel Create(string id, IEnumerable<IModel> modelsList);
}
public class ViewModelFactory : IViewModelFactory<Model1>
{
public IViewModel Create(string id, IEnumerable<IModel> modelsList)
{
return new ViewModel1(targetId, modelsList);;
}
}
public class FactoryLocator
{
public static IViewModelFactory<T> GetFactory<T>(T parameters)
{
return ServiceLocator.Current.GetInstance<IViewModelFactory<T>>();
}
}
And then I will use it that way:
public void CreateAndAddVM(IList<IModel> modelsList)
{
var factory = FactoryLocator.GetFactory(modelsList.FirstOrDefault());
var vm = factory.Create(_id, modelsList);
ViewModels.Add(vm);
}
When I get to the FactoryLocator, the type is actually IModel interface and not a Model1/2/3.
Is there any way to make it work somehow? Or maybe another way to implement this requirement?
You should start with interface defined like this
public interface IViewModelFactory<T> where T : IModel
{
IViewModel Create(string id, IEnumerable<T> modelsList);
}
and it will actually force correct typing on future implementers.
As I mentioned in my comment. At this moment, anyone can create a view model with a model that may not be intended for it.
For example, if your ViewModel depends on Model1, there's nothing stopping me from providing a list of Model2 to the Create
method in your factory.
Consider the following:
public abstract class ViewModelBase<TModel> where TModel : IModel
The example above will allow your ViewModel to specify what Model it represents, however this goes by the assumption that a ViewModel only has one Model, which may not always be the case.
In this scenario, your ViewModelBase
class should have an ID, and a Model property for the TModel.
Ensure that IModel
inherits from INotifyPropertyChanged
, this will allow TModel
to be an ObservableCollection
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.