这只是我一直在考虑的问题,并且想知道它是否存在,或者它是否有益。
我正在使用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);
}
}
不是将“Customer”作为类型参数传递给会话,我认为传递“ICustomer”并以某种方式将nHibernate配置为执行IoC会很酷。这甚至是可能的,还是有益的?
答案 0 :(得分:1)
我无法看到这样做的任何灵活性,但要实现你所要求的,你可以尝试:
public abstract class AbstractCustomerRepository<T> : ICustomerRepository where T : class, ICustomer
{
public ICustomer Retrieve(int id)
{
return _session.Get<T>(id);
}
}
public class CustomerRepository : AbstractCustomerRepository<Customer>
{
}
答案 1 :(得分:1)
当我们开始设计我们的应用程序时,我有完全相同的想法。但是,很快我们就遇到了一些仅使用基于接口的类型的问题,所以我们通过使用具体类型和松散的存储库来妥协,这意味着Customer和ICustomerRepository。
我想回忆一下我们遇到的问题,但现在我已经被淘汰了。
答案 2 :(得分:1)
向NHibernate投掷ICustomer
没有什么好处。 NHibernate本身应该只是一个带有几个挂钩的黑匣子,你可以把你的嘲笑附加到。你可以在NHibernate中模拟实现;它并不关心里面使用的是什么对象。
在模拟此方法时,您可以使用NHibernate中的ISession
和IQuery
以及您自己代码中的ICustomerRepository
来完成所有这些操作。无需添加额外的抽象。
哦,顺便问一下,为什么当您的存储库已经存在时,NHibernate会作为额外的IoC容器?
答案 3 :(得分:1)
将您的IOC容器(Unity)与NHibernate集成的一种方法是使用Unity来解析您传递给NHibernate的类型。
这实现了我认为你的目标,即在一个地方只有接口和实现之间的映射。
public CustomerRepository : ICustomerRepository
{
Type customerType;
// ISession[Factory] injection omitted for brevity
public CustomerRepository(IUnityContainer container)
{
registration = container.Registrations.FirstOrDefault(
x => x.RegisteredType.Equals(ICustomer));
if(registration == null)
{
throw new ApplicationException(
"No ICustomer implementation was registered.");
}
customerType = registration.MappedToType;
}
public ICustomer Retrieve(int id)
{
return _session.Get(customerType, id);
}
}
显然,你不能使用NHibernate的泛型重载,但我认为它们都有非泛型的等价物。
您必须参考具体实施的另一个地方是您的FNH ClassMap<T>
。
答案 4 :(得分:0)
如果您要使用ICustomer界面,这会建议您替换客户其他内容吗?会是这种情况吗?如果是这样的话呢?
您的客户类应该是您的域的一部分,以及产品,订单等其他实体。您的域应该构成整个应用程序的核心部分。我认为您的努力应该转向保持您的域实体与您的NHibernate数据访问代码分离,而您似乎是通过Repository接口实现的。
如果你想创建一个具有特定Customer实现的基础Customer,那么使用Nhibernate非常支持的继承:
public abstract class Customer { }
public class EnterpriseCustomer : Customer { }
public class SmbCustomer : Customer { }
public class IndividualCustomer : Customer { }
当你调用return _session.Get<Customer>(id);
时,NHibernate足以实例化正确的类型而无需自己明确地投射它。
也许这就是你所追求的。看看有关继承的NHibernate文档:http://nhibernate.info/doc/nh/en/index.html#inheritance
答案 5 :(得分:0)
使用IOC的一个例子是找到ICustomerRepository的具体实现
//在您的客户端代码中。
ICustomerRepository dao = ServiceFactory.GetServiceInstance<ICustomerRepository>();
// ServiceFactory的框架
public static class ServiceFactory
{
private WindsorContainer m_container;
public static T GetServiceInstance<T>()
{
// use your IOC to resolve your <T>
return m_container.Resolve<T>();
}
}
在上面的例子中,我使用Castle Windsor作为我的IOC。请调整您的实现以使用Unity Block。
我希望你能理解我的想法。