Geo*_*uer 11 lazy-loading inversion-of-control
在进行延迟加载时,注入数据访问依赖项的正确方法是什么?
例如,我有以下类结构
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
}
Run Code Online (Sandbox Code Playgroud)
如何将_customer_dao引用到事务对象中?如果我希望事务至少看起来像POCO,那么对构造函数的要求似乎就没有意义.是否可以让Transaction对象直接引用Inversion of Control Container?这也似乎很尴尬.
像NHibernate这样的框架如何处理这个?
我建议不同的东西...使用延迟加载类:
public class Lazy<T>
{
T value;
Func<T> loader;
public Lazy(T value) { this.value = value; }
public Lazy(Func<T> loader { this.loader = loader; }
T Value
{
get
{
if (loader != null)
{
value = loader();
loader = null;
}
return value;
}
public static implicit operator T(Lazy<T> lazy)
{
return lazy.Value;
}
public static implicit operator Lazy<T>(T value)
{
return new Lazy<T>(value);
}
}
Run Code Online (Sandbox Code Playgroud)
一旦你得到它,你就不需要在你的对象中注入dao了:
public class Transaction
{
private static readonly Lazy<Customer> customer;
public Transaction(Lazy<Customer> customer)
{
this.customer = customer;
}
public Customer Customer
{
get { return customer; } // implicit cast happen here
}
}
Run Code Online (Sandbox Code Playgroud)
创建未绑定到数据库的Transcation对象时:
new Transaction(new Customer(..)) // implicite cast
//from Customer to Lazy<Customer>..
Run Code Online (Sandbox Code Playgroud)
从存储库中的数据库重新生成事务时:
public Transaction GetTransaction(Guid id)
{
custmerId = ... // find the customer id
return new Transaction(() => dao.GetCustomer(customerId));
}
Run Code Online (Sandbox Code Playgroud)
发生了两件有趣的事情: - 您的域对象可以在有或没有数据访问的情况下使用,它会变得无知的数据访问.唯一的小麻烦就是能够传递给对象而不是对象本身的函数. - Lazy类是内部可变的,但可以用作不可变值.readonly关键字保持其语义,因为其内容不能在外部更改.
如果希望字段可写,只需删除readonly关键字即可.在分配新值时,由于隐式转换,将使用新值创建新的Lazy.
编辑:我在这里写博客:
http://www.thinkbeforecoding.com/post/2009/02/07/Lazy-load-and-persistence-ignorance
我通常会像上面那样在构造函数中进行依赖项注入,但仅在调用“get”时才进行延迟加载,如下所示。不确定这是否是您正在寻找的纯粹方法,但它确实一步消除了“脏”构造函数 DI/延迟加载;)
public class Product
{
private int mProductID;
private Supplier mSupplier;
private ISupplierService mSupplierService;
public Product()
{
//if you want your object to remain POCO you can use dual constr
//this constr will be for app use, the next will be for testing
}
public Product(ISupplierService SupplierService)
{
mSupplierService = SupplierService;
}
public Supplier Supplier {
get {
if (mSupplier == null) {
if (mSupplierService == null) {
mSupplierService = new SupplierService();
}
mSupplier = mSupplierService.GetSupplierByProductID(mProductID);
}
return mSupplier;
}
set { mSupplier = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2955 次 |
最近记录: |