X

Using Lazy and abstract wrapper class to lazy-load complex system parameters

.NET Framework 4.0 introduced new class called Lazy<T> and I wrote blog post about it: .Net Framework 4.0: Using System.Lazy<T>. One thing is annoying for me – we have to keep lazy loaded value and its value loader as separate things. In this posting I will introduce you my Lazy<T> wrapper for complex to get system parameters that uses template method to keep lazy value loader in parameter class.

Problem with original implementation

Here’s the sample code that shows you how Lazy<T> is usually used. This is just sample code, don’t focus on the fact that this is dummy console application.

class Program
{
    static void Main(string[] args)
    {
        var temperature = new Lazy<int>(LoadMinimalTemperature);

        Console.WriteLine("Minimal room temperature: " + temperature.Value);
        Console.ReadLine();
    }

    protected static int LoadMinimalTemperature()
    {
        var returnValue = 0;

        // Do complex stuff here

        return true;
    }
}

The problem is that our class with many lazy loaded properties will grow messy if it has all value loading code inside it. This code may be complex for more than one parameter and in this case it is better to use separate class for this parameter.

Defining base class for parameters

As a first step I will define base class for all lazy-loaded parameters. This class is wrapper around Lazy<T> and it also offers one template method that parameter classes have to override to provide loaded data.

public abstract class LazyParameter<T>
{
    private Lazy<T> _lazyParam;

    public LazyParameter()
    {
        _lazyParam = new Lazy<T>(Load);
    }

    protected abstract T Load();

    public T Value
    {
        get { return _lazyParam.Value; }
    }
}

It is also possible to extend Lazy<T> but I don’t prefer to do it as Lazy<T> has six constructors we have to take care of. Also I don’t like to expose Lazy<T> public interface to users of my parameter classes.

Creating parameter class

Now it’s time to create our first parameter class. Notice how few stuff we have in this class besides overridden Load() method.

public class MinimalRoomTemperature : LazyParameter<int>
{
    protected override int Load()
    {
        var returnValue = 0;

        // Do complex stuff here

        return returnValue;
    }
}

Using parameter class is simple. Here’s my test code.

class Program
{
    static void Main(string[] args)
    {
        var parameter = new MinimalRoomTemperature();
        Console.WriteLine("Minimal room temperature: " + parameter.Value);
        Console.ReadLine();
    }
}

Conclusion

Lazy<T> is useful class that you usually don’t want to use outside from API-s. I like this class but I don’t like when people are using this class directly in application code. In this posting I showed you how to use Lazy<T> with wrapper class to get complex parameter loading code out from classes that use this parameter. We ended up with generic base class for parameters that you can also use as base for other similar classes (you have to find better name to base class in this case).

Liked this post? Empower your friends by sharing it!

View Comments (5)

  • I'd prefer this:

    public class LazyParameter {
    private readonly Lazy _lazyParam;

    public LazyParameter( Func load ) {
    _lazyParam = new Lazy( load );
    }

    public T Value {
    get { return _lazyParam.Value; }
    }
    }

    Which is a bit cleaner to use:

    var temp = new LazyParameter( () => 1 + 30 ).Value;

    var page = new LazyParameter(
    () => HttpContext.Current.Request.QueryString["page"]
    ).Value;

  • Thanks for feedback, AndyT! Your solution is fine when there is not much code in method that retrieves actual value. But in the case of complex logic that needs more code my solution works better because you have separate class with its own methods.

  • But Isent the point of lazy loading data the data is ökades when/if the gode hits the parameter?

    This code loars the data in the constructor?

    How skuld this be used in a buissnes class?

  • This code doesn't load data in constructor. Lazy accepts Func as constructor argument but it doesn't run this Func immediately.

    When Value is asked then Lazy checks of data is already loaded and if it isn't then it runs this Func to get data.

Related Post