为每个 ViewModel 创建一个 ISession 实例
这是我的问题:我正在使用以下工具构建一个桌面应用程序:
- Caliburn
- Ninject
- NHibernate
我所有的视图模型和存储库都是用 Ninject 实例化的。我的存储库都需要在其构造函数中使用 ISession。
我想遵循ayende关于ViewModel的建议:每个ViewModel打开一个新会话。
是否可以配置 Ninject 在创建 ViewModel 时打开一个新会话,并在该视图模型使用的存储库中使用此会话?
我查看了 Ninject 的 InScope 函数,以及 NHibernate 中的 ICurrentSessionContext 接口,但我不知道如何对所有这些进行建模以获得我想要的东西......
以前有人做过类似的东西吗?
预先感谢
迈克
here is my problem: I'm building a desktop application, with the following tools:
- Caliburn
- Ninject
- NHibernate
All my view models and repositories are instanciated with Ninject. My repositories all need an ISession in their constructor.
I'd like to follow ayende's advice concerning the ViewModels: each ViewModel opens a new session.
Is it possible to configure Ninject to open a new session when a ViewModel is created, and use this session inside the repositories used by this view model?
I had a look to the InScope function of Ninject, as well as the ICurrentSessionContext interface in NHibernate, but I don't know how to model all of that to get what I want...
Did someone make something like that before?
Thanks in advance
Mike
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我利用 ViewModel 生命周期解决了类似的场景:我创建了一个由存储库实现的 ISessionAware 接口(使用 SetSession 方法),然后通过 ViewModel 的 OnInitialize 方法中的 ISessionAware 初始化存储库(当虚拟机启动时,该方法由 Caliburn 强制执行)由 ScreenConductor 管理)。
使用反射来检查保存存储库的属性,我可以将所有基础设施放在 BaseDataVM 类上。
我认为在容器中使用范围会更优雅,但我不知道 Ninject。
I solved a similar scenario leveraging the ViewModel lifecycle: I created an ISessionAware interface (with a SetSession method) to be implemented by repositories, then I initialized the repositories through ISessionAware in the OnInitialize method of the ViewModel (which is enforced by Caliburn when the VM is managed by a ScreenConductor).
Using reflection to inspect the properties holding the repositories, I could put all the infrastructure on a BaseDataVM class.
Using a scope in the container would be more elegant, I think, but I don't know Ninject.
我有一个非常相似的项目(除了我没有使用 Caliburn)并且也一直在尝试找出如何做到这一点。我确实想出了一种非常适合使用 Ninject 的 InScope() 方法进行构造函数注入的方法。
我有一个名为 IoC 的静态类,它包装了对 Ninject 内核的访问。由于依赖项全部注入到构造函数中,因此上下文仅在创建对象时才相关。因此,为上下文提供的内容并不重要,但 Guid 感觉是安全的选择。 Program.OpenSession() 是打开新 ISession 的静态方法。
用法是:
表单的构造函数签名是:
我通过绑定上的 InScope 验证,用于构造 frmCompanyViewer 的同一个 ISession 也用于构造 companyRepository。如果我删除 InScope,则会使用两个 ISession。
编辑添加:这也可以,请参阅评论。对于实际应用程序来说,这应该是线程安全的。我将方法名称更改为
ConstructInContext
以澄清上下文仅在对象构造期间适用。I have a very similar project (except I'm not using Caliburn) and have been trying to figure out how to do this as well. I did come up with one method that works well for constructor injection using Ninject's InScope() method.
I have a static class called IoC that wraps access to Ninject's kernel. Since the dependencies are all injected into the constructor, the context is only relevant when the object is being created. So it doesn't matter what is supplied for context, but a Guid feels like the safe choice. Program.OpenSession() is a static method to open a new ISession.
Usage is:
The form's constructor signature is:
I verified that with InScope on the bindings, the same ISession that is used to construct frmCompanyViewer is also used to construct companyRepository. If I remove InScope then two ISessions are used.
Edited to add: This would also work, see comments. This should be made thread safe for a real application. I changed the method name to
ConstructInContext
to clarify that the context only applies during object construction.我们在 Unhaddins 中通过 AOP 实现了这一点。
称为“每笔业务交易的对话”。
在谷歌中搜索
We have this with AOP, in unhaddins.
Is called "Conversation per Business Transaction".
search in google
在这里你有;)
http://groups. google.com/group/unhaddins/browse_thread/thread/29eca74a83df5faf/d9fab4062d4cb4c4?lnk=gst&q=ninject#d9fab4062d4cb4c4
here you have ;)
http://groups.google.com/group/unhaddins/browse_thread/thread/29eca74a83df5faf/d9fab4062d4cb4c4?lnk=gst&q=ninject#d9fab4062d4cb4c4
好吧,感谢 ninject 小组,我找到了解决方案。
这里的解决方案是在绑定ISession时使用函数InScope,并在IContext变量中浏览以检查服务。如果请求层次结构中的一项服务可分配给我的视图模型的基类,我将使用上下文作为范围。
因此,第一次将 ISession 注入到 ViewModel 的构造函数中时,将使用一个新范围。并且 ViewModel 构造函数内对 ISession 的所有后续调用都将在相同范围内解析。然后只为我的 ViewModel 创建一个会话。
这是代码:
并且视图模型的构造函数必须包含依赖于 ISession 的所有注入依赖项:
希望有帮助
Well, I've found a solution thanks to the ninject group.
The solution here is to use the function InScope when I bind ISession, and browse in the IContext variable to inspect the services. If one service in the request hierarchy is assignable to the base class of my view models, I use the context as scope.
So the first time an ISession will be injected in the constructor of my ViewModel, a new scope is used. And all subsequent calls to ISession inside the constructor of the ViewModel will be resolved with the same scope. And then only one session is created for my ViewModel.
Here is the code:
And the constructor of the viewmodel must contains all the injected dependencies which rely on the ISession:
Hope that helps