Welcome to My Nerditorium

Thoughts on coding, gaming, and nerdy media.

Persistence Ignorant Lazy Loading for Your Hand-Rolled DAL in .NET 4.0 Using Lazy

This post is a brief update to the .NET 3.5 article I posted about P.I. lazy loading. The only major change I have made to the code is to use the new Lazy<T> class that was introduced in .NET 4.0. This considerably cleans up the LazyLoadingList<T> class from the previous post.

Here is the new LazyLoadingList<T>:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
public class LazyLoadingList<T> : IList<T>
{
     private Lazy<IList<T>> _lazyList;

     public LazyLoadingList(Lazy<IList<T>> lazyList)
     {
        _lazyList = lazyList;
     }

     #region Implementation of IEnumerable

     public IEnumerator<T> GetEnumerator()
     {
        return _lazyList.Value.GetEnumerator();
     }

     IEnumerator IEnumerable.GetEnumerator()
     {
        return _lazyList.Value.GetEnumerator();
     }

     #endregion

     #region Implementation of ICollection<T>

     public void Add(T item)
     {
        _lazyList.Value.Add(item);
     }

     public void Clear()
     {
        _lazyList.Value.Clear();
     }

     public bool Contains(T item)
     {
        return _lazyList.Value.Contains(item);
     }

     public void CopyTo(T[] array, int arrayIndex)
     {
        _lazyList.Value.CopyTo(array, arrayIndex);
     }

     public bool Remove(T item)
     {
        return _lazyList.Value.Remove(item);
     }

     public int Count
     {
        get
        {
           return _lazyList.Value.Count;
        }
     }

     public bool IsReadOnly
     {
        get
        {
           return ((ICollection<T>)_lazyList.Value).IsReadOnly;
        }
     }

     #endregion

     #region Implementation of IList<T>

     public int IndexOf(T item)
     {
        return _lazyList.Value.IndexOf(item);
     }

     public void Insert(int index, T item)
     {
        _lazyList.Value.Insert(index, item);
     }

     public void RemoveAt(int index)
     {
        _lazyList.Value.RemoveAt(index);
     }

     public T this[int index]
     {
        get
        {
           return _lazyList.Value[index];
        }
        set
        {
           _lazyList.Value[index] = value;
        }
     }

     #endregion
}

Here are the changes to the invoking code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CompanyDAO : ICompanyDAO
{
   List<Company> _companiesInDatabase = new List<Company>
         {
             new Company(){Name = "ACME"},
             new Company(){Name = "Hardees"}
         };

   #region Implementation of ICompanyDAO

   public Company GetByName(string name)
   {
      // Write to console to demonstrate when loading is happening
      Console.WriteLine("---Loading Company---");

      // Pretend we are calling / mapping from a store procedure
      var company = _companiesInDatabase.Where(x => x.Name == name).First();


      // Create / add the lazily loaded collection
      if (company != null)
      {
         var lazyLoader = new Lazy<IList<Employee>>(
               () =>
                     {
                        var employeeDAO = new EmployeeDAO();
                        return employeeDAO.GetByCompanyName(name).ToList();
                     }
            );

         company.Employees = new LazyLoadingList<Employee>(lazyLoader);
      }

      return company;
   }

   #endregion
}

Source Code