C# 使用unity初始化层次树视图模型

C# 使用unity初始化层次树视图模型,c#,wpf,mvvm,unity-container,prism,C#,Wpf,Mvvm,Unity Container,Prism,我正在调查应用程序中使用Prism的变化。目前,我正在努力初始化层次结构 基本上我有一个基类,其他类继承它,简化如下: public class NodeViewModel : INodeViewModel { Node Node { get; private set; } public ObservableCollection<INodeViewModel> ChildNodeViewModels { get; private set; } public

我正在调查应用程序中使用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
        }
    }
}
ChildNodeViewModels.Add((INodeViewModel)System.Activator.CreateInstance(ModelToViewModelMappingDictionary.GetMappedViewModelType(childNode.GetType()), System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, new object[] { childNode }, null));
然后我有一个初始化行,如下所示:

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
        }
    }
}
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的
    参数覆盖
    需要
    字符串参数名
    。如上面的代码所示,由于parameterName不是常量而失败,每个继承的类都有自己的parameterName
提前谢谢

  • 你的把戏很普通。更常见的是:
  • InheritedViewModel

    其中:

    节点设备模型

    当然:

    INodeViewModel

  • Prism的部分功能是从容器中获取所需的实例,如下所示:
  • 容器(或您将如何称呼它)。GetInstance(或其任何名称)>()

    您需要首先在INodeViewModel的容器InheritedViewModel中注册,才能使其正常工作

    我喜欢你现在的选择,因为你避免了用这种方式建立很多工厂

    广告2:

    必须为unity提供参数名,因此必须手动反映构造函数并找到要覆盖的参数名。然后可以通过unity解析视图模型并传入模型。但是有一个陷阱!使用参数替代进行解析时,您可以替代与替代中的参数名称匹配的任何参数,无论是在层次结构中的任何位置,也不管是何种类型。在最好的情况下,类型不匹配,您会得到一个异常,在最坏的情况下,错误的依赖项被默默地注入。祝你调试的愉快

    建议:

    坚持当前生成视图模型的方式,并在构建对象时注入依赖项。这也有缺点,因为您不能使用构造函数注入,并且需要对容器的引用,但我更喜欢这些,而不是不可预测的参数重写

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


    我不完全理解你的答案,你能澄清一点并将其映射到我在问题中提供的代码示例吗?在你的引导程序中,你可以配置你的容器。注册一个接口时,应该创建继承它的类。稍后,当您向容器请求实现它的东西时,您将得到您注册的类型的实例。是的,我明白。但我不知道如何将参数添加到构造函数中。当您调用Container.Resolve(params[]parmas)时,我知道每个继承的NodeVM的参数名都可能不同。谢谢你的回答。我也一直在考虑类似的方法,但这反过来又使构造函数中的其他部分变得复杂。经过大量的深入阅读,我认为我滥用了容器来创建对象。我现在要尝试的是让容器注入一个抽象工厂。无论如何,这将是一个更好的方法,因为工厂才是真正需要的。然后,混凝土工厂可以通过构造函数注入请求它自己的依赖项。是的,这总是可能的,我通常会推荐它,但如果你必须创建几十个或数百个工厂,它们基本上都做相同的事情(即为树节点创建视图模型),这会变得很烦人。因此,我喜欢您的attribute plus activator.createinstance方法……目前我们有+100个节点设备模型