NHibernate 与控制反转
这只是我一直在思考的事情,想知道它是否存在,或者是否有好处。
我正在使用 Unity 进行控制反转和依赖注入。我也在使用流畅的 nHibernate 进行 ORM。我想知道是否有一种方法可以配置 nHibernate 以将接口作为其类型参数并为我执行 IoC,或者将它们一起使用的最佳方法是什么。
例如,如果我有一个使用存储库模式的客户对象,我可能会有 2 个接口(ICustomer、ICustomerRepository)以及 2 个具体实现(Customer、CustomerRepository)。在具体的 CustomerRepository 中,我必须将其直接绑定到 Customer 对象才能使用 nHIbernate。
public class CustomerRepository : ICustomerRepository
{
public ICustomer Retrieve(int id)
{
return _session.Get<Customer>(id);
}
}
我认为传递“ICustomer”并以某种方式配置 nHibernate 来执行 IoC 会很酷,而不是将“Customer”作为类型参数传递给会话。这可能吗,或者有什么好处吗?
This is just something I've been thinking about and was wondering if it exists, or even if its beneficial at all.
I'm doing inversion of control and dependency injection using Unity. I'm also doing ORM with fluent nHibernate. I was wondering if there was a way to either configure nHibernate to take interfaces as its type parameters and do IoC for me, or what the best way to use them together would be.
For instance, if I had a customer object using a repository pattern I would possibly have 2 interfaces (ICustomer, ICustomerRepository) as well as 2 concrete implementations (Customer, CustomerRepository). In the concrete CustomerRepository I would have to tie it directly to the Customer object in order to use nHIbernate.
public class CustomerRepository : ICustomerRepository
{
public ICustomer Retrieve(int id)
{
return _session.Get<Customer>(id);
}
}
Instead of passing "Customer" as a type parameter to the session, I think it would be cool to pass "ICustomer" and somehow have nHibernate configured to do the IoC. Is this even possible, or beneficial at all?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
当我们开始设计应用程序时,我有完全相同的想法。然而,很快我们就遇到了仅使用基于接口的类型的一些问题,因此我们通过使用具体类型和松散存储库(即 Customer 和 ICustomerRepository)进行妥协。
我试图回忆我们遇到了什么问题,但现在我一片空白。
When we started designing our application, I had the exact same idea. However, pretty soon we ran into some issues with using only interface based types, so we compromised, by using concrete types and loose repositories, meaning Customer and ICustomerRepository.
I'm trying to recall what issues we ran into, but right now I'm blanked out.
将
ICustomer
放入 NHibernate 中并没有真正的优势。 NHibernate 本身应该只是一个带有几个钩子的黑盒子,您可以将模拟附加到其中。你可以模拟 NHibernate 中的实现;它并不真正关心里面使用了什么对象。模拟此方法时,您可以使用 NHibernate 中的
ISession
和IQuery
以及您自己的代码中的ICustomerRepository
来完成所有这些操作。无需添加额外的抽象。哦,顺便说一句,当你的存储库已经是一个额外的 IoC 容器时,为什么还要使用 NHibernate 作为额外的 IoC 容器呢?
There is no real advantage in throwing in an
ICustomer
into NHibernate. NHibernate itself should just be a black box with a couple of hooks where you can attach your mocks to. As you can mock the implementation in NHibernate; it doesn't really care what objects are used inside.When mocking this method, you can do all of this with the
ISession
andIQuery
from NHibernate, and theICustomerRepository
from your own code. No need to add an extra abstraction.Oh, and btw, why have NHibernate as an additional IoC container when your repository already is?
将 IOC 容器 (Unity) 与 NHibernate 集成的一种方法是使用 Unity 解析要传递给 NHibernate 的类型。
这实现了我认为您的目标,即仅在一处实现接口和实现之间的映射。
显然,您不能使用 NHibernate 的泛型重载,但我认为它们都有非泛型等效项。
您必须引用具体实现的另一个地方是 FNH
ClassMap
中。One way to integrate your IOC container (Unity) with NHibernate, is to use Unity to resolve the type you'll pass to NHibernate.
This accomplishes what I think is your aim, which is to have in only one place the mapping between interface and implementation.
Obviously, you can't use NHibernate's generic overloads, but I think they all have non-generic equivalents.
The one other place in which you'll have to reference the concrete implementation is in your FNH
ClassMap<T>
s.我看不到这样做有任何很大的灵活性,但为了实现你所要求的,你可以尝试:
I can't see any great flexibility from doing this but to achieve what you're asking you could try:
使用 IOC 的一个示例是
在客户端代码中查找 ICustomerRepository // 的具体实现。
// ServiceFactory 的框架
在上面的示例中,我使用 Castle Windsor 作为我的 IOC。请调整您的实现以使用 Unity Block。
我希望你能明白我的想法。
An example of using IOC would be to find the concrete implementation of ICustomerRepository
// in your client code.
// a framework of the ServiceFactory
In the example above, I am using Castle Windsor as my IOC. Please adapt your implementation to use Unity Block.
I hope you'd get my idea across.
如果您打算有一个 ICustomer 接口,这是否表明您想用其他东西代替 Customer?会是这样吗?如果是的话那么用什么?
您的客户类应该是您的域的一部分,以及其他实体(例如产品、订单等)。您的域应该构成整个应用程序的中心部分。我认为您应该努力使域实体与 NHibernate 数据访问代码解耦,这似乎是通过存储库接口实现的。
如果您想创建具有特定 Customer 实现的基本 Customer,那么请使用继承,Nhibernate 对此支持非常好:NHibernate
足够强大,可以在您调用 return _session.Get(id);< 时实例化正确的类型。 /code> 无需自己显式转换。
也许这就是你所追求的。查看有关继承的 NHibernate 文档: http://nhibernate.info/ doc/nh/en/index.html#继承
If you're going to have an ICustomer interface, this would suggest you want to substitute Customer for something else? Would this be the case? If so then with what?
Your Customer class should be part of your domain, along with other entities such as Product, Order etc etc. Your domain should form the central part of your entire application. I think your efforts should move toward keeping your domain entities decoupled from your NHibernate data access code, which you seem to be achieving with Repository interfaces.
If you want to create a base Customer with specific Customer implementations, then use inheritance, which Nhibernate supports really well:
NHibernate is powerful enough to instantiate the correct type when you call
return _session.Get<Customer>(id);
without having to explicitly cast it yourself.Perhaps this is what you're after. Have a look at the NHibernate documentation on inheritance: http://nhibernate.info/doc/nh/en/index.html#inheritance