MVVM光,Ninject在大多通知区域的应用 [英] MVVM Light, Ninject in a mostly notification area application

查看:299
本文介绍了MVVM光,Ninject在大多通知区域的应用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我建设有通知区域图标支持.NET 4的WPF桌面应用程序。

应用有几个窗口,这显示在启动时,再关闭掉,只通知区域图标仍然存在。

的通知区域图标纯粹是WPF控件,我从这个 $ C $的CProject例子。

由于我的应用程序仍应当所有的窗口都关闭了,我即使设定运行

  ShutdownMode =OnExplicitShutdown

在App.xaml中。

我将介绍我的一种体系结构和启动机制的想法,你告诉我,我错了,如果可能指正。

在App.xaml.cs我创建一个Ninject StandardKernel ,姑且称之为 appKernel 并加载Ninject模块分成它。起初只有一个接口是由Ninject解决 - 一个 heartbeatManager 实例。一个HeartbeatManager是一类我刨使用的:

一)托管我NotifyIcon的实例作为场变量,以便它reamins可见只要类的实例是在存储器

二)关机事件的执行情况,我会在app.xaml.cs并明确关闭的应用程序认购,当心跳类要求它。

在这一点上 heartbeatManager 实例被创建只是留在记忆挂起。

在App.xaml中我设置了的StartupUri =MainWindow.xaml以创建主窗口并显示。继主窗口尝试解析它在App.xaml中定义的静态ViewModelLocator实例数据上下文中的MVVM光ViewModelLocator模式:

 < Application.Resources>
    <的ViewModels:ViewModelLocator X:键=定位器D:IsDataSource =真/>
< /Application.Resources>

ViewModelLocator实例被创建,并在构造函数中进行初始化另一个StandardKernel(是否有任何其他类型的内核我在这一点上喊使用?的),将被用于解决视图模型绑定。提供了一个主窗口的视图模型以满足窗户的要求,整个应用程序继续运行。

有一个很重要的启示,就是hearbeatManger实例绑定在一个singletone范围的接口定义,因此需要它作为一个构造函数的参数,视图模型能够解决,并获得已创建的实例。将这种依赖性解析工作,如果视图模型和heartbeatManager在一个不同的内核加载?如果没有,我怎么能解决这个问题?

时的上述情景规划有什么好的架构,明智的,它是在code实现的,或有我犯了一个错误,当我通过架构?

思维
解决方案

  

...此时一个heartbeatManager实例创建仅仅留在存储器挂...


如果它与你的内核注册的,它不是导致它在内存中挂任何魔法 - 只要它坚持围绕作为内核/容器一样。该容器也许应该是你的App类的成员,因为您的应用程序类,只要(编译器生成)的坚持围绕方法做,你应该处理它的应用程序无论如何关机


  

...继主窗口尝试解析它在App.xaml中定义的静态ViewModelLocator实例数据上下文中的MVVM光ViewModelLocator模式...


我不知道这会与NInject拌匀。这是一个依赖注入容器,而不是一个服务定位器容器(即使它使用引擎盖下一个)。 NInject(以及类似的框架)的主要目的是为了避免要求您使用Service Locator模式,而是注入所有的依赖关系。


  

... ViewModelLocator实例被创建并在构造函数初始化它的另一个StandardKernel ...


除非你的情况是相当复杂(这真的不是这个应用程序),那么我建议坚持一个NInject内核。

建议的解决方案

视图模型定位器类本身并没有做很多你比其他让你拆你的初始化逻辑,并做取决于你是否是在设计模式或运行模式选择初始化。你可以实现与NInject模块相同(其中你的评论链接视图模型定位的文章已经使用)。

我建议,而不是使用一个视图模型定位器,您指定的所有的在你的模块类的部件,并做 IsInDesignMode 逻辑在加载方法。

这可能是一个有点棘手与MVVM不过,因为视图模型需要绑定到一个对象属性,你没有创建,而不能标注。

有解决这个直接在NInject,而不是诉诸一个服务定位器的一些方法:


  • 在您的视图使用依赖注入,使得它需要一个视图模型。结果
    如果不使用构造器注入(如你在评论中提到)工作,使用财产,而不是注射,与它的二传手转发到的DataContext 自定义属性。

  • 使用<一个href=\"https://github.com/ninject/ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context\"相对=nofollow> NInject工厂方法( ToMethod )来创建视图,并绑定视图模型在每个工厂方法的看法。结果
    例如。 绑定&LT;&的MainView GT;()ToMethod。(上下文=&gt;新建的MainView(){= DataContext的新MainViewModel()});

如果可以的话,我会去的第二个方法。这样,你的观点不具有处理数据绑定和不具有任何code后面。这也是很容易理解,会让你避免注册在内核两种观点并视图模型,并且将让你避免任何形式的知名界面为你浏览模式。

I need an application architecture advise.

I am building a .Net 4 WPF desktop application with notification area icon support.

Application has a few windows, that show up on startup, then get closed, and only the Notification Area icon remains.

The notification area icon is purely WPF control that I got from this codeproject example.

Since my app should remain running even when all the windows are closed, I have set a

ShutdownMode="OnExplicitShutdown"

in App.xaml.

I will describe my idea of an architecture and startup mechanism, and you tell me where I am going wrong and correct me if possible.

In App.xaml.cs I create a Ninject StandardKernel, let's call it appKernel and load Ninject modules into it. At first only one interface is to be resolved by Ninject - a heartbeatManager instance. A HeartbeatManager is a class I am planing to use for:

a) Hosting my NotifyIcon instance as a field variable, so that it reamins visible as long as the class instance is in memory.

b) Implementation of shutdown event, that I will subscribe for in app.xaml.cs and shutdown the application explicitly, when the heartbeat class requests it.

At this point a heartbeatManager instance is created just left to hang in the memory.

In App.xaml I set the StartupUri="MainWindow.xaml" so the MainWindow is created and shown. Following the MVVM Light ViewModelLocator pattern the MainWindow tries to resolve it's data context from the static ViewModelLocator instance defined in App.xaml:

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

ViewModelLocator instance is created and in the constructor it initializes another StandardKernel (is there any other type of kernel I shout use at this point?) that will be used to resolve the view model bindings. A MainWindow's view model is provided to satisfy the windows's request and the whole application continues to operate.

A very important implication, is that the hearbeatManger instance is bound to an interface definition in a singletone scope, so that view models that require it as a constructor parameter can resolve and get the already created instance. Will such dependency resolution work, if the view model and the heartbeatManager are loaded in a different kernels? If not, how can I solve this problem?

Is the above planned scenario any good architecture-wise, is it implementable in code, or have I made a mistake when I was thinking through the architecture?

解决方案

...At this point a heartbeatManager instance is created just left to hang in the memory...

If it is registered with your kernel, it isn't any magic that causes it to hang in memory - it will stick around as long as the kernel/container does. That container should probably be a member of your App class, since your app class sticks around as long as the (compiler generated) Main method does, and you should dispose it on app shutdown anyhow.

...Following the MVVM Light ViewModelLocator pattern the MainWindow tries to resolve it's data context from the static ViewModelLocator instance defined in App.xaml...

I'm not sure this will mix well with NInject. It is a Dependency Injection container, not a Service Locator container (even though it uses one under the hood). The main purpose of NInject (and similar frameworks) is to avoid requiring you to use the Service Locator pattern, and instead to inject all your dependencies.

...ViewModelLocator instance is created and in the constructor it initializes another StandardKernel...

Unless your scenario is quite complicated (which it really isn't for this app), then I suggest sticking to a single NInject kernel.

Suggested Solution

The view model locator class itself doesn't do much for you other than let you split up your initialization logic, and do selective initialization depending on whether you're in design mode or runtime mode. You could achieve the same with NInject modules (which the view model locator article you linked in comments already uses).

I suggest that instead of using a view model locator, you specify all your components in your module class, and do the IsInDesignMode logic in the Load method.

This might be a bit tricky with MVVM though, since the view model needs to bind to an object property you didn't create, and can't annotate.

There are a few ways to solve this directly in NInject, instead of resorting to a service locator:

  • Use Dependency Injection on your view, making it require a view model.
    If this doesn't work using constructor injection (as you mentioned in your comments), use property injection instead, with a custom property that forwards its setter to DataContext.
  • Use NInject factory methods (ToMethod) to create your view, and bind the view model to the view in each factory method.
    E.g. Bind<MainView>().ToMethod(context => new MainView() { DataContext = new MainViewModel() });

If you can, I'd go for the second method. This way your view doesn't have to handle data binding, and doesn't have to have any code behind. It is also simple to understand, would let you avoid having to register both views and view models in the kernel, and would let you avoid making any sort of well known interface for your view model.

这篇关于MVVM光,Ninject在大多通知区域的应用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆