在进行延迟加载时,注入数据访问依赖项的正确方法是什么?
例如,我有以下类结构
class CustomerDao : ICustomerDao public Customer GetById(int id) {...} class Transaction { int customer_id; //Transaction always knows this value Customer _customer = null; ICustomerDao _customer_dao; Customer GetCustomer() { if(_customer == null) _customer = _customer_dao.GetById(_customer_id); return _customer }
如何将_customer_dao引用到事务对象中?如果我希望事务至少看起来像POCO,那么对构造函数的要求似乎就没有意义.是否可以让Transaction对象直接引用Inversion of Control Container?这也似乎很尴尬.
像NHibernate这样的框架如何处理这个?
我建议不同的东西...使用延迟加载类:
public class Lazy{ T value; Func loader; public Lazy(T value) { this.value = value; } public Lazy(Func loader { this.loader = loader; } T Value { get { if (loader != null) { value = loader(); loader = null; } return value; } public static implicit operator T(Lazy lazy) { return lazy.Value; } public static implicit operator Lazy (T value) { return new Lazy (value); } }
一旦你得到它,你就不需要在你的对象中注入dao了:
public class Transaction { private static readonly Lazycustomer; public Transaction(Lazy customer) { this.customer = customer; } public Customer Customer { get { return customer; } // implicit cast happen here } }
创建未绑定到数据库的Transcation对象时:
new Transaction(new Customer(..)) // implicite cast //from Customer to Lazy..
从存储库中的数据库重新生成事务时:
public Transaction GetTransaction(Guid id) { custmerId = ... // find the customer id return new Transaction(() => dao.GetCustomer(customerId)); }
发生了两件有趣的事情: - 您的域对象可以在有或没有数据访问的情况下使用,它会变得无知的数据访问.唯一的小麻烦就是能够传递给对象而不是对象本身的函数. - Lazy类是内部可变的,但可以用作不可变值.readonly关键字保持其语义,因为其内容不能在外部更改.
如果希望字段可写,只需删除readonly关键字即可.在分配新值时,由于隐式转换,将使用新值创建新的Lazy.
编辑:我在这里写博客:
http://www.thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance