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

标签 c# lazy-loading

如果这个问题已经得到解答,我深表歉意,但我找不到任何答案。

在最近的一个面试问题中,我被问及如何实现延迟加载。场景如下:

解决方法:

  • 网站项目
    • 默认.aspx
  • 对象收集项目
    • 订单
    • 订单项
  • 服务层
    • 订单服务
  • 存储库层
    • 订单库

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

问题是“我将如何延迟加载 Order 对象。即有一个 Order 对象,网站调用 myOrder.LineItems。

我的第一个想法是订单对象会调用订单服务来获取订单项,但这不是好的设计,因为对象需要了解服务,而服务需要了解对象。自然地,网站可以调用订单服务,将订单/订单 ID 传递给它以获取订单项,但我们如何才能让这一点不可见呢?所以 Order 对象保存了它的所有数据,但有些只在需要时加载?

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

乔恩

最佳答案

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

  • 了解 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;}
  } 
}

这是没有 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;}
 }
}

更新 这是项目布局。有关于耦合订单和存储库的评论。实际上并非如此,因为存储库耦合到装饰器,而不是顺序。

  • 对象收集项目
    • 订单
    • 订单项
  • 服务层
    • 订单服务
  • 存储库层
    • 订单库
    • OrderDecorator

关于c# - 对象在自己的DLL中时如何实现自己的延迟加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4810629/

相关文章:

c# - Lazy<T> 延迟加载错误 : A field initializer cannot reference the non-static field, 方法或属性

c# - 是否应该重构此 C# 代码以改用 Lazy<T> 类?

ipad - 在不阻塞主线程的情况下从文件中延迟加载 UIImages?

javascript - Jstree 延迟加载和展开所有问题

c# - 你如何移植一个开源项目?

c# - 如何在没有 Json.Net 依赖的情况下使用 SQLite-Net 扩展(使用替代 ITextBlobSerializer)?

c# - Entity Framework 5 查询中的错误数据类型

grails - Criteria查询中的Grails LazyClob

c# - 如何验证字符串是英文的?

c# - Asp.net Core 中 IFormFile 字段的 xunit 测试