Wpf 使用MEF时创建子视图模型

Wpf 使用MEF时创建子视图模型,wpf,mvvm,mef,Wpf,Mvvm,Mef,我有一个传统的MVVM方法,例如一个名为“PatientManagementViewModel”的视图模型,它由一个名为“PatientManagementView”的视图使用。所有东西都是使用MEF注入的,所以我自己不创建任何实例 现在假设“PatientManagementViewModel”有一个属性Patients,它是“PatientViewModel”的ObervableCollection。我现在创建“PatientViewModel”实例并传递所选患者的操作如下: var pat

我有一个传统的MVVM方法,例如一个名为“PatientManagementViewModel”的视图模型,它由一个名为“PatientManagementView”的视图使用。所有东西都是使用MEF注入的,所以我自己不创建任何实例


现在假设“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);