.NET delegates

Tue, Aug 7, 2007 3-minute read

Some years ago, when someone mentioned delegates I would shudder, and think back of all the times when I had tried to use them to something useful, and All I could think of at the time was to use them for events that other objects could subscribe to. This is also a nice feature, but when you think about it delegates is so much more.

I have started using delegates more heavily, and primarily to do Lazy Loading of data from a database. Lazy Loading is a technique where you only load the data when the application need it.  Lets say you have a class Customer, with a lot of properties, including an Orders collection. Instead of loading all orders and all other data that is related to the Customer, why not just load the data when the application makes a request for it, by invoking the get method of the Orders collection.

People would perhaps argue that it would require for the business objects to know the database structure, or if done a little more clever, need a reference to a Data Access Layer, but no, thats not neccesary, since you can use delegates for it.

Consider the following delegate:

public delegate List<T> LoadDataDelegate<T>();

This delegate states that it will return a list of objects of type T.

Okay then consider the following class:

public class Customer
{
    /// <summary>
    /// Creates a new instance of the Customer class
    /// </summary>
    /// <param name="ordersDelegate"></param>
    public Customer(LoadDataDelegate<Order> ordersDelegate)
    {
        this.ordersDelegate = ordersDelegate;
    }

    private LoadDataDelegate<Order> ordersDelegate;

    private List<Order> orders;
    /// <summary>
    /// Gets a List of orders for the current Customer
    /// </summary>
    public List<Order> Orders
    {
        get 
        {
            if (orders == null)
            {
                orders = ordersDelegate();
            }
            return orders; 
        }
    }
}

And the following Mock data layer:

public class DAL
{
    public List<Order> GetAllOrdersForCustomer(long customerID)
    {
        string sql = "select * from orders where customer_id=@customer_id";
        //etc
        //load into list
    }

    public Customer GetCustomer(long customerID)
    {
        Customer c = new Customer(delegate() { return GetAllOrdersForCustomer(customerID); });
        
        //load other data from the database
        return c;
    }
}

These two classes and the delegates, show a very simple way of using delegates for something intelligent and create an object that is capable of loading data from the database on demand, without knowing anything about Datalayers, SQL or anything else.

Nice right :-D

Consider implementing all methods that can create, read, update and delete an object as delegates and all you would ever need to expose to your application is the business objects, and perhaps a few factory methods that could create new instances of objects with the delegates assigned to actual methods in your data layers :-D