Architecture MVVM Light,Ninject,主要用于通知区域应用程序

Architecture MVVM Light,Ninject,主要用于通知区域应用程序,architecture,mvvm,ninject,mvvm-light,Architecture,Mvvm,Ninject,Mvvm Light,我需要一个应用程序架构建议 我正在构建一个支持通知区域图标的.NET4WPF桌面应用程序 应用程序有几个窗口,在启动时显示,然后关闭,只保留通知区域图标 通知区域图标是我从codeproject示例中获得的纯WPF控件 因为即使所有窗口都关闭,我的应用程序也应该保持运行,所以我设置了一个 ShutdownMode="OnExplicitShutdown" 在App.xaml中 我将描述我对体系结构和启动机制的想法,你告诉我哪里出了问题,如果可能,请纠正我 在App.xaml.cs中,我创建了一

我需要一个应用程序架构建议

我正在构建一个支持通知区域图标的.NET4WPF桌面应用程序

应用程序有几个窗口,在启动时显示,然后关闭,只保留通知区域图标

通知区域图标是我从codeproject示例中获得的纯WPF控件

因为即使所有窗口都关闭,我的应用程序也应该保持运行,所以我设置了一个

ShutdownMode="OnExplicitShutdown"
在App.xaml中

我将描述我对体系结构和启动机制的想法,你告诉我哪里出了问题,如果可能,请纠正我

在App.xaml.cs中,我创建了一个Ninject
StandardKernel
,我们将其命名为
appKernel
,并将Ninject模块加载到其中。首先,Ninject-a
heartbeatManager
实例只能解析一个接口。HeartbeatManager是我计划使用的一个类:

a) 将我的NotifyIcon实例作为字段变量托管,这样只要类实例在内存中,它就可以显示

b) shutdown事件的实现,我将在app.xaml.cs中订阅该事件,并在heartbeat类请求时显式关闭该应用程序

此时,将创建一个
heartbeatManager
实例,以便挂起在内存中

在App.xaml中,我设置了
StartupUri=“MainWindow.xaml”
以便创建并显示主窗口。遵循MVVM Light ViewModelLocator模式,主窗口尝试从App.xaml中定义的静态ViewModelLocator实例解析其数据上下文:

<Application.Resources>
    <ViewModels:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
</Application.Resources>

创建ViewModelLocator实例,并在构造函数中初始化另一个StandardKernel(此时是否有其他类型的内核供我使用?),该内核将用于解析视图模型绑定。提供了一个主窗口的视图模型来满足windows的要求,整个应用程序继续运行

一个非常重要的含义是,hearbeatManger实例绑定到单音作用域中的接口定义,因此需要它作为构造函数参数的视图模型可以解析并获取已创建的实例。如果视图模型和heartbeatManager加载到不同的内核中,这种依赖关系解析会起作用吗?如果没有,我如何解决这个问题

上述计划的场景在架构方面是否良好,是否可以在代码中实现,或者在思考架构时是否犯了错误

…此时将创建一个heartbeatManager实例,以便挂起在内存中

如果它是在内核中注册的,那么它不会因为任何魔法而挂起在内存中——它会一直挂在内核/容器上。该容器可能是应用程序类的一个成员,因为只要(编译器生成的)
Main
方法存在,应用程序类就会一直存在,并且您应该在应用程序关闭时处理它

…遵循MVVM Light ViewModelLocator模式,主窗口尝试从App.xaml中定义的静态ViewModelLocator实例解析其数据上下文

我不确定这会不会和NInject混在一起。它是一个依赖注入容器,而不是服务定位器容器(即使它在引擎盖下使用一个)。NInject(和类似框架)的主要目的是避免要求您使用服务定位器模式,而是注入所有依赖项

…ViewModelLocator实例已创建,并在构造函数中初始化另一个StandardKernel

除非您的场景非常复杂(这对于这个应用程序来说确实不复杂),否则我建议您坚持使用一个NInject内核

建议的解决方案

视图模型定位器类本身对您没有多大帮助,只允许您分割初始化逻辑,并根据您处于设计模式还是运行时模式进行选择性初始化。您可以使用NInject模块实现同样的效果(这是一个很好的例子)

我建议不要使用视图模型定位器,而是在模块类中指定所有组件,并在
Load
方法中执行
IsInDesignMode
逻辑

但是,这对于MVVM来说可能有点棘手,因为视图模型需要绑定到未创建的
对象
属性,并且不能进行注释

有几种方法可以直接在NInject中解决此问题,而不是求助于服务定位器:

  • 在视图上使用依赖项注入,使其需要视图模型。
    如果使用构造函数注入(正如您在注释中提到的)无法实现此功能,请使用属性注入,使用自定义属性将其setter转发到
    DataContext
  • 使用(
    ToMethod
    )创建视图,并将视图模型绑定到每个factory方法中的视图。
    例如,
    Bind().ToMethod(context=>newmainview(){DataContext=newmainviewmodel()})

如果可以的话,我会选择第二种方法。这样,视图就不必处理数据绑定,也不必有任何代码隐藏。它也很容易理解,可以避免在内核中同时注册视图和视图模型,还可以避免为视图模型创建任何众所周知的接口。

我很难弄清楚这里的实际问题是什么。您谈到应用程序关闭,实例挂起在内存中,但您没有解释为什么您担心这些事情。应用程序类将保持不变,因为它是在生成的
Main
方法中创建的,如果将其放在应用程序类中,容器/内核应该保持不变,而实例化的类应该保持不变,只要容器保持不变(尤其是单例)。为什么有两个内核/容器?还有,这个mi