user1702269
user1702269

Reputation:

How to Implement Lazy Loading on a Large Number of Properties

I have a Class with multiple property-code like this snippet:

IFoo a;
public IFoo Foo
{
    get
    {
        if (a == null)
        {
            // load a
            ...
        }
        return a;
    }
}


IBar b;
public IBar Bar
{
    get
    {
        if (b == null)
        {
            // load b
            ...
        }
        return b;
    }
}

I have over 20 Propertys, where always the interface is different, not the loading-structure. I feel this code is not optimal.

Is there a better solution? Maybe something generic, such as (not working):

T b;
public T Bar<T>
{
    get
    {
        if (b == null)
        {
            // load b
            ...
        }
        return b;
    }
}

Upvotes: 0

Views: 982

Answers (4)

giacomelli
giacomelli

Reputation: 7407

What you are looking for is an implemenation of Lazy Loading Pattern.

There are some commons ways to get it done, like: Virtual Proxy, Value Holder and Ghost. As @bjeger mentioned, you can use Lazy<T> to resolve your problem, but look and study the above implemenations will let you know what is better for your specific case.

Here is some samples using C#: Four Ways to Implement Lazy Loading in C#.

Upvotes: 1

Mark
Mark

Reputation: 1371

One way to get shorter properties at least is Lazy<T>:

Lazy<IBar> b = new Lazy<IBar>();
public IBar Bar
{
  get
  {
    return b.Value;
  }
}

When b.Value is first called it will call the default constructo of IBar. There are multiple overloads having to do with thread safety and calling other constructors. See: http://msdn.microsoft.com/en-us/library/dd642331(v=vs.110).aspx

Upvotes: 0

Paweł Bejger
Paweł Bejger

Reputation: 6366

Try to use Lazy<T> construct which in fact is a syntactic sugar of your code.

Example from MSDN (define how to lazy load the object a a Func in the constructor, thread-safe):

lazyLargeObject = new Lazy<LargeObject>(() => 
{
    LargeObject large = new LargeObject(Thread.CurrentThread.ManagedThreadId);
    // Perform additional initialization here. 
    return large;
});

then the value will be fetched the first time you try to access the object like this:

LargeObject large = lazyLargeObject.Value;

Upvotes: 1

Mike Zboray
Mike Zboray

Reputation: 40818

use LazyInitializer.EnsureInitialized:

using System.Threading;

IFoo a;
public IFoo Foo
{
    get
    {
        return LazyInitializer.EnsureInitialized(ref a, () => { /* load a */ });
    } 
}

Upvotes: 0

Related Questions