How to implement your own lazy loading when objects in your own DLL

If this has already been answered, I apologize, but I could not find an answer to this question.

In an interview I recently asked, I was asked how to implement Lazy Loading. The scenario is as follows:

decision:

  • project website
    • default.aspx
  • collection project
    • Order
    • Lineitem
  • Service level
    • OrderService
  • Storage tier
    • OrderRepository

The Order object has an IList. The order repository has a method for returning all orders (to be faster, it did not return all linear elements for each order, so it will be zero).

Question: "How would I do lazy loading for an Order.Ie object. There is an Order object, and the website calls myOrder.LineItems.

My first thought was that the Order object called the order service to get the rows, but this is not a very good design, because objects must know about the service and the service should know about the objects. Naturally, a website can call an order service that passes an order / order identifier to it to get rows, but how can we make this bit invisible? Thus, the Order object stores all its data, but some are loaded only as and when / if required?

Thank you and hope everything made sense.

John

+4
source share
2 answers

There would be three things that I, as an interviewer, sought in the answer.

  • Knowledge of how ORM structures handle lazy loading.
  • Confirmation that you will not introduce this into production without taking into account the existing structure.
  • The actual design of the "homegrown" solution.

This is how I would answer this question.

Lazy loading of a common piece of functionality implemented by ORM infrastructures such as NHibernate or Entity Framework. My first attempt will be to use one of these frameworks (point 1)

If the ORM framework cannot be resolved, I would do lazy loading using an interception infrastructure such as intercepting a castle or intercepting unity (point 2).

To implement lazy loading from scratch, I would use the Decorator template (bonus point), a subclass of the Order class, and describe the lazy loading behavior there. Here is a design showing the relevant properties:

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;} } } 

And here is the version without Lazy<> quirkiness. After editing, to make sure the code strictly matches the decoratorโ€™s template, the lazy version doesnโ€™t actually add anything, so I would just go with the version below.

 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 . Here is the layout of the project. There was a comment about the relationship of the order and the repository. In fact, this is not so, since the repository is associated with the decorator, and not with order.

  • collection project
    • Order
    • Lineitem
  • Service level
    • OrderService
  • Storage tier
    • OrderRepository
    • OrderDecorator
+8
source

You can store a lazy link to a list using, for example, the Lazy class.

One of the constructors of this class gets Func<T> , which is the function used to create / get the actual value on request.

A possible solution would be to insert this function into an Order object initialized with something like:

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

After that, it simply binds Lazy<ICollection<LineItem>> to the property.

+2
source

Source: https://habr.com/ru/post/1337222/


All Articles