使用MEF时创建子视图模型

时间:2011-03-02 12:19:15

标签: wpf mvvm mef

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

现在假设'PatientManagementViewModel'具有属性Patients,这是'PatientViewModel'的ObervableCollection。我现在要做的是创建一个'PatientViewModel'实例并传递选定的患者,如下所示:

var patientViewModel = _container.GetExportedValue<IPatientViewModel>();
patientViewModel.Patient = patient;

然而,这是有效的,我想知道这是否有意义。将患者传递给构造函数会更好,因为没有患者,“PatientViewModel”不能存在:

var patientViewModel = new PatientViewModel(patient);

然后我不能使用依赖注入。

所以问题是:注入子视图模型是否有意义,或者我应该只注入主视图模型,并在不注入的情况下实例化所有子视图模型?

1 个答案:

答案 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);

这里的缺点是,当你使用构造函数参数时,你会对参数的类型,计数,顺序等进行编译时检查。