如何在自己的DLL中的对象时实现自己的延迟加载

Jon*_*Jon 4 c# lazy-loading

如果已经回答了这个问题我道歉,但我找不到任何答案.

在我最近的一个采访问题中,我被问到如何实现Lazy Loading.方案如下:

解:

  • 网站项目
    • Default.aspx的
  • 对象集合项目
    • 订购
    • 的LineItem
  • 服务层
    • OrderService
  • 存储库层
    • OrderRepository

Order对象将具有IList.订单存储库将有一个返回所有订单的方法(为了更快,它不会返回每个订单的所有订单项,因此它将为null).

问题是"如何为Order对象进行延迟加载.即有一个Order对象,网站调用myOrder.LineItems.

我的第一个想法是Order对象将调用Order Service来获取lineitems,但这不是好的设计,因为Objects需要知道该服务,并且服务需要知道对象.当然,网站可以调用订单服务传递订单/订单ID来获取线条,但是我们怎么能让那个位看不见呢?所以Order对象包含它的所有数据,但有些只是在需要的时候加载?

谢谢,希望一切都有意义.

乔恩

Igo*_*aka 8

作为面试官,我会在答案中寻找三件事.

  • 了解ORM框架如何处理延迟加载
  • 确认在不考虑现有框架的情况下,您不会在生产中实现此功能.
  • 实际设计的"本土"解决方案.

这就是我回答这个问题的方法.

延迟加载由NHibernate或Entity Framework等ORM框架实现的通用功能.我的第一次尝试是使用其中一个框架(第1点)

如果ORM框架是不可能的,我将使用拦截框架(如Castle Interception或Unity Interception)实现延迟加载.(第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;}
  } 
}
Run Code Online (Sandbox Code Playgroud)

这是没有Lazy<>幻想的版本.编辑后确保代码严格符合装饰器模式,懒惰版本实际上并没有添加任何东西,所以我只是使用下面的版本.

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;}
 }
}
Run Code Online (Sandbox Code Playgroud)

更新这是项目布局.关于将订单和存储库耦合的评论.实际情况并非如此,因为存储库与装饰器耦合,而不是订单.

  • 对象集合项目
    • 订购
    • 的LineItem
  • 服务层
    • OrderService
  • 存储库层
    • OrderRepository
    • OrderDecorator

  • @Jon实际上,它没有.如果仔细观察,服务引用是*OrderDecorator*,而不是订单.这与ORM框架的作用很接近. (2认同)