我有一种传统的MVVM方法,例如名为'PatientManagementViewModel'的视图模型,由名为'PatientManagementView'的视图使用。一切都是使用MEF注入的,所以我自己不创建任何实例。
现在假设'PatientManagementViewModel'具有属性Patients,这是'PatientViewModel'的ObervableCollection。我现在要做的是创建一个'PatientViewModel'实例并传递选定的患者,如下所示:
var patientViewModel = _container.GetExportedValue<IPatientViewModel>();
patientViewModel.Patient = patient;
然而,这是有效的,我想知道这是否有意义。将患者传递给构造函数会更好,因为没有患者,“PatientViewModel”不能存在:
var patientViewModel = new PatientViewModel(patient);
然后我不能使用依赖注入。
所以问题是:注入子视图模型是否有意义,或者我应该只注入主视图模型,并在不注入的情况下实例化所有子视图模型?
答案 0 :(得分:1)
您可以执行以下操作。您可以使用常规构造函数创建子视图模型,然后在实例上调用ComposeParts
来注入所有内容:
var patientViewModel = new PatientViewModel(patient);
_container.ComposeParts(patientViewModel);
但是出于各种原因,每次这样做都不是很好。为了解决这种情况并封装MEF的使用,我创建了一个帮助服务来创建视图模型。它被称为IViewModelFactory
,它的外观如下:
[Export(typeof(IViewModelFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
internal class ViewModelFactory : IViewModelFactory
{
[ImportingConstructor]
public ViewModelFactory(CompositionContainer container) {
Contract.Requires(container != null);
Container = container;
}
protected CompositionContainer Container { get; private set; }
public T Create<T>(params object[] args) where T : class {
T result;
try {
bool populateDependencies = false;
if (args == null || args.Length == 0) {
// There are no parameters for contructor, so
// try to create an instance by asking the container.
result = Container.GetExportedValueOrDefault<T>();
if (result == null) {
// The view model is not exported. Just create an instance using reflection
// and then populate all the dependencied using the container.
result = Activator.CreateInstance<T>();
populateDependencies = true;
}
}
else {
// There are constructor parameters. Create an instance using those parameters
// and then populate all the dependencied using the container.
result = (T)Activator.CreateInstance(typeof(T), args);
populateDependencies = true;
}
// Populate dependencies if needed
if (populateDependencies) {
Container.ComposeParts(result);
}
// Initialize the object if applicable
var initializable = result as IInitializable;
if (initializable != null) {
initializable.Initialize();
}
}
catch (Exception ex) {
throw new ViewModelCreationException(
string.Format(
"Unable to create and configure an instance of view model of type {0}. An error occured. See inner exception for details.",
typeof (T)), ex);
}
return result;
}
}
使用此工厂,您可以创建如下的子视图模型:
var patientViewModel = ViewModelFactory.Create<PatientViewModel>(patient);
这里的缺点是,当你使用构造函数参数时,你会对参数的类型,计数,顺序等进行编译时检查。