Wpf 使用MEF时创建子视图模型
我有一个传统的MVVM方法,例如一个名为“PatientManagementViewModel”的视图模型,它由一个名为“PatientManagementView”的视图使用。所有东西都是使用MEF注入的,所以我自己不创建任何实例Wpf 使用MEF时创建子视图模型,wpf,mvvm,mef,Wpf,Mvvm,Mef,我有一个传统的MVVM方法,例如一个名为“PatientManagementViewModel”的视图模型,它由一个名为“PatientManagementView”的视图使用。所有东西都是使用MEF注入的,所以我自己不创建任何实例 现在假设“PatientManagementViewModel”有一个属性Patients,它是“PatientViewModel”的ObervableCollection。我现在创建“PatientViewModel”实例并传递所选患者的操作如下: var pat
现在假设“PatientManagementViewModel”有一个属性Patients,它是“PatientViewModel”的ObervableCollection。我现在创建“PatientViewModel”实例并传递所选患者的操作如下:
var patientViewModel = _container.GetExportedValue<IPatientViewModel>();
patientViewModel.Patient = patient;
但是我不能使用依赖注入
所以问题是:注入子视图模型有意义吗?还是我应该只注入主视图模型,不注入而实例化所有子视图模型?您可以执行以下操作。您可以使用常用构造函数创建子视图模型,然后在实例上调用
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;
}
}
[导出(类型(IViewModelFactory))]
[PartCreationPolicy(CreationPolicy.Shared)]
内部类ViewModelFactory:IViewModelFactory
{
[导入构造函数]
公共ViewModelFactory(合成容器){
Contract.Requires(container!=null);
容器=容器;
}
受保护的CompositionContainer容器{get;private set;}
公共T创建(参数对象[]参数),其中T:class{
T结果;
试一试{
bool populatedependences=false;
if(args==null | | args.Length==0){
//constructor没有参数,所以
//尝试通过询问容器来创建实例。
结果=Container.GetExportedValueOrDefault();
如果(结果==null){
//未导出视图模型。只需使用反射创建一个实例
//然后使用容器填充所有依赖项。
结果=Activator.CreateInstance();
populateDependencies=true;
}
}
否则{
//存在构造函数参数。请使用这些参数创建实例
//然后使用容器填充所有依赖项。
结果=(T)Activator.CreateInstance(typeof(T),args);
populateDependencies=true;
}
//如果需要,填充依赖项
if(填充依赖项){
容器。组件(结果);
}
//初始化对象(如果适用)
var initializable=结果可初始化;
if(可初始化!=null){
initializable.Initialize();
}
}
捕获(例外情况除外){
抛出新的ViewModelCreationException(
字符串格式(
“无法创建和配置类型为{0}的视图模型实例。发生错误。有关详细信息,请参阅内部异常。”,
类型(T)),ex);
}
返回结果;
}
}
使用此工厂,您可以创建如下子视图模型:
var patientViewModel = ViewModelFactory.Create<PatientViewModel>(patient);
var patientViewModel=ViewModelFactory.Create(patient);
这里的缺点是,当您使用构造函数参数时,会丢失对参数类型、计数、顺序等的编译时检查。“PatientManagementViewModel”有一个属性Patients,这是“PatientViewModel”的ObervableCollection。您能解释一下吗?我看不出有什么问题。出口工厂会让这个更干净。MEF的.NET 4版本不支持它,但下一个版本将有它,Codeplex预览版和Silverlight已经有了它。@Daniel-很有趣。。。你能提供一个链接吗?和
var patientViewModel = ViewModelFactory.Create<PatientViewModel>(patient);