2011-01-26 64 views
4

如果這已被回答,我很抱歉,但我找不到任何答案。如何實現自己的延遲加載當對象在自己的DLL

在最近我有一個採訪問題中,我被問到如何實現延遲加載。該方案如下:

解決方案:

  • 網站項目
    • 的Default.aspx
  • 對象集合項目
    • 訂購
    • 的LineItem
  • 服務層
    • OrderService
  • 庫層
    • OrderRepository

訂單對象將有一個IList。訂單倉庫將有一個方法來返回所有訂單(要更快,它不會返回每個訂單的所有線條,因此它將爲空)。

的問題是:「我會怎麼做延遲加載訂單對象。即有一個訂單對象和網站調用myOrder.LineItems。

我首先想到的是訂單對象將調用命令向獲得線條,但這不是好的設計,因爲Objects需要知道關於服務的信息,服務需要知道關於這些對象的信息。當然,網站可以調用訂單服務傳遞訂單/訂單ID以獲得lineitems,但是我們怎樣才能使這一點看不見?所以Order對象保存它的所有數據,但是有些只是在需要時加載?

謝謝,並希望所有的製作森SE。

喬恩

回答

8

作爲一個採訪者,我會有三樣東西在尋找答案。

  • 知識的ORM框架如何處理延遲加載
  • 確認,你不會不考慮現有的框架生產實現這一點。
  • 「本土」解決方案的實際設計。

這就是我將如何回答這個問題。

延遲加載由NHibernate或實體框架等ORM框架實現的常見功能。我的第一次嘗試將使用這些框架之一(點1)

如果一個ORM框架沒有問題,我將使用攔截框架(如攔截攔截或攔截)來實施延遲加載(點2)。

爲了實現從零開始的延遲加載,我將使用Decorator模式(獎勵點),Order類的子類並在那裏定義延遲加載行爲。這裏是設計顯示相關屬性:

class Order { 
public int ID {get;set;} 
public virtual IList<OrderLine> Lines{get;set;} 
} 

interface IOrderRepository { 
    Order GetOrder(id); 
    IList<OrderLine> GetOrderLines(Order order); 
} 

class OrderService { 

IOrderRepository _repository; 

public OrderService(IOrderRepository repository) { 
    _repository = repository; 
} 

public Order GetOrder(int id) { 
    return new OrderDecorator(_repository.GetOrder(id)); 
} 
} 

public class OrderDecorator : Order { 
    public OrderDecorator (IOrderRepository repository) { 
    _OrderLines = new Lazy<IList<OrderLine>>(()=>repository.GetOrderLines(this)); 
    } 

    Lazy<IList<OrderLine>> _OrderLines; 

    public override IList<OrderLine> Lines { 
    get { 
     if (base.OrderLines == null) 
     base.OrderLines = _OrderLines.Value; 
     return base.OrderLines; 
    } 
    set {base.OrderLines=value;} 
    } 
} 

而這裏是版本沒有Lazy<> fanciness。編輯完成以確保代碼嚴格符合裝飾器模式後,懶惰版本實際上並沒有添加任何內容,所以我只想使用下面的版本。

public class OrderDecorator : Order { 
    public OrderDecorator (IOrderRepository repository) { 
    _Repo = repository; 
    } 
    IOrderRepository _Repo; 

    public override IList<OrderLine> Lines { 
    get { 
    if (base.OrderLines == null) 
     base.OrderLines = repository.GetOrderLines(this); 

    return base.OrderLines; 
    } 
    set {base.OrderLines=value;} 
} 
} 

UPDATE下面是該項目的佈局。有關於耦合訂單和存儲庫的評論。實際情況並非如此,因爲存儲庫與裝飾器耦合,而不是順序。

  • 對象集合項目
    • 訂購
    • 的LineItem
  • 服務層
    • OrderService
  • 庫層
    • OrderRepository
    • OrderDecorator
+0

點之一,兩個都是非常有效和有益的。代碼示例(據我所知)仍然與Order Object和IOrderRepo/Service緊密相關。感謝您的幫助和意見。 – Jon 2011-01-27 11:30:18

2

可以存儲一個懶惰參考使用列表,例如Lazy類。

該類的構造函數之一接收Func<T>這是一個函數,用於在請求時實例化/檢索實際值。

一個可能的解決方案是注入該功能爲訂單對象,具有類似初始化:

var getlines =() => orderService.GetLineItems(orderId); 

在此之後,它只是包裹Lazy<ICollection<LineItem>>與屬性。