使用unity初始化分层树视图模型

时间:2017-03-20 15:55:20

标签: c# wpf mvvm unity-container prism

我正在调查我们使用Prism的应用程序的变化。目前我正在努力进行层次结构的初始化。

基本上我有一个其他类继承的基类,简化如下:

public class NodeViewModel : INodeViewModel
{
    Node Node { get; private set; }
    public ObservableCollection<INodeViewModel> ChildNodeViewModels { get; private set; }

    public NodeViewModel(IUnityContainer container, Node node)
    {
        Node = node;
        ChildNodeViewModels = new ObservableCollection<INodeViewModel>();

        foreach (Node childNode in Node.ChildNodes)
        {
            // Some initialization code
        }
    }
}

到目前为止,我没有使用容器,所以我们只有Node参数。每个继承的类都有一个属性,我们将其用于模型到视图模型映射。

[ModelToViewModelMapping(typeof(InheritedNode ))]
public class InheritedViewModel: NodeViewModel
{
    public InheritedViewModel(InheritedNode inheritedNode)
        : base(inheritedNode)
    {
    }
}

然后我有一个像这样的初始化行:

ChildNodeViewModels.Add((INodeViewModel)System.Activator.CreateInstance(ModelToViewModelMappingDictionary.GetMappedViewModelType(childNode.GetType()), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, new object[] { childNode }, null));

我的问题是双重的。

  • 我不知道带有属性的旧技巧是否是映射的常用解决方案。我想不是,但它可以轻松地将事物保持在一起并且易于管理。我不确定viewmodellocator是一个很好的解决方案,我对它完全是新的,我还没试过。
  • 如何进行初始化。 Resolve方法使用我可以以某种方式解析的类型(我的属性解决方案,viewmodellocator,...)但Unity的ParameterOverride需要string parameterName。如上面的代码所示,因为parameterName不是常量而失败,每个继承的类都有自己的parameterName。

提前致谢!

2 个答案:

答案 0 :(得分:1)

广告1:

我喜欢你当前的选择,因为你避免以这种方式创建很多工厂。

广告2:

您必须为unity提供参数名称,因此您必须手动反映构造函数并找到要覆盖的参数的名称。然后,您可以通过统一解析视图模型并传入模型。 但是有一个问题!当使用参数覆盖进行解析时,您覆盖任何参数,这些参数恰好与覆盖中的参数名称匹配,层次结构中的任何位置,无论何种类型。在最好的情况下,类型不匹配,并且您得到一个异常,在最坏的情况下,静默注入错误的依赖项。有趣的调试......

建议:

坚持使用当前生成视图模型的方法,并在构造对象时注入依赖项。这也有缺点,因为你不能使用构造函数注入,你需要对容器的引用,但我更喜欢那些相当不可预测的参数覆盖。

var viewModel = Activator.CreateInstance(...);
_container.BuildUp( viewModel );

internal class MyChildViewModel
{
    [Dependency]
    public ISomeService MyDependency { get; set; }
}

答案 1 :(得分:0)

  1. 你的伎俩很常见。更常见的是:
  2. InheritedViewModel&lt; InheritedNode&gt;

    还在哪里:

    NodeViewModel&lt; T&gt;

    当然:

    INodeViewModel&lt; T&gt;

    1. Prism的部分功能是从容器中获取您需要的实例:
    2. 容器(或者你将如何调用它).GetInstance(或其所谓的)&lt; INodeViewModel&lt; InheritedNode&gt;&gt;()

      您需要先在容器中注册InheritedViewModel&lt; T>使用INodeViewModel&lt; T>为了工作