Object Factories with Lazy Loading in C#

cyberjoe

Newcomer
Joined
Nov 1, 2006
Messages
12
I'm looking for a lazy loading solution in c#.

The idea is, to have a kind of object factory, which will be responsible for creating my entity objects.
When a property of such an object is accesed and it is not yet loaded, the factory
(or a magic watcher) will be able to pause the execution flow for a while (maybe that step is not necessary)
load the missing data (don't know how to specify, from where to load that data----maybe via attributes) and
return to the flow.

My entity objects, do not have a possibility to load the missing data by themselves, because they
are only data containers having private members, which are accessible via public properties.
These objects need to be filled with their data from outside, and therefore many lazy loading solutions
won't work here.

Maybe anyone of you knows the solution for my problem?

Thank You in advance!


Greetz!
cyberjoe
 
I think you may need to be more specific on certain points. Does the data all come from one source (or one kind of source)? Or is it all channeled through one class? There needs to be some way to make the connections between the container and the data source, whether it be a URL, a RegistryKey object, a file path, etc.. This connection could be stored in the data container, or it could, for example, be stored in a static dictionary where the data object is the key and the data source is the value (I personally would prefer the former).

The object will need some way of invoking the initializer, which means that it will need to do something like (1)Invoke the object that accesses data so that that object may initialize the data container, which requires that the data container maintain a reference to the object that will initialize it, and possibly a string to identify the data source (URL/filename) or (2)be able to access the data and initialize itself. Also, the data container class would need to perform a check on every method and property access (or, at least, every member that should trigger lazy initialization). Most likely you will encapsulate this into a single method. Either way, it will have a performance penalty (most likely minor, though).

Here is a very simple shell for a lazily initialized class, and a possible derivation.
C#:
/// <summary>
/// Defines a base class for lazy initialization
/// </summary>
abstract class LazyBase
{
    public LazyBase() {
    }

    /// <summary>Tracks whether or not this object is initialized.</summary>
    bool initialized = false;

    /// <summary>
    /// Gets whether this object is initialized.
    /// </summary>
    public bool IsInitialized {
        get { return initialized; }
    }


    /// <summary>
    /// This method should be called at the beginning of any method or property
    /// that may invoke lazy initialization.
    /// </summary>
    protected void CheckInitialize() {
        if(!initialized)
            PerformLazyInitialize();
    }

    /// <summary>
    /// This method should be overridden to implement initialization. The
    /// overriding implementation must call the base method.
    /// </summary>
    protected virtual void PerformLazyInitialize() {
        initialized = true;
    }
}
 
A base class that could provide data to your lazily initialized objects.
C#:
/// <summary>
/// Defines a base class for a data source that will initialize objects.
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class DataBase<T> where T:LazyBase
{
    /// <summary>
    /// Override to initialize an object with data from this data source.
    /// </summary>
    /// <param name="dataObject">The object to initialize.</param>
    public abstract void Initialize(T dataObject);
}
A data container class that supports lazy intialization (just as an example).
C#:
/// <summary>
/// Define an object to hold data (in our case, an int).
/// </summary>
public class LazyIntDataContainer:LazyBase
{
    /// <summary>The source of our data. It might be smarter to incorporate
    /// this into your base class.</summary>
    RandomDataSource data;
    public LazyIntDataContainer(RandomDataSource data) {
        this.data = data;
    }

    /// <summary>
    /// This is the action that will be performed when this object needs to be initialized. 
    /// Here we use our "DataBase" object to intialize the object. We don't
    /// really need to do that, but it allows us to use different types of data
    /// sources to initialize the same kind of data container (provided that
    /// the data source inherits from the DataBase class).
    /// </summary>
    protected override void PerformLazyInitialize() {
        base.PerformLazyInitialize();

        data.Initialize(this);
    }

    private int value;
    /// <summary>
    /// Gets/sets this data containers data.
    /// </summary>
    public int Value {
        get {
            // The object must be initialized before this property can be accessed.
            CheckInitialize();
            
            return value; 
        }
        set {
            // The object must be initialized before this property can be accessed.
            CheckInitialize();

            this.value = value; 
        }
    }
}
The data source for our lazy data container. Since this is for demonstrative purposed only, this class simply provides random data.
C#:
/// <summary>
/// Data source that provides random integers.
/// </summary>
public class RandomDataSource: DataBase<LazyIntDataContainer>
{
    /// <summary>Random number generator.</summary>
    Random rand = new Random();
    /// <summary>
    /// Initialize data containers.
    /// </summary>
    /// <param name="dataObject">Data container to initialize.</param>
    public override void Initialize(LazyIntDataContainer dataObject) {
        dataObject.Value = rand.Next();
    }
}
The LazyIntDataContainer class does not benefit here from lazy initialization, but it demonstrates using the abstract classes I posted for lazy initialization and separation between the data and initialization.
 
Before coming up with any solution, I'd be curious why you're wanting to use some object oriented techniques, like a factory pattern with lazy loading, yet ignoring the most important part - objects work with their data, they should not be simple "structs" filled with properties. A class with no public methods is a bad smell indeed.

Marble has some great ideas. I'd keep it simple by asking yourself how you plan on using your object - where do you plan on getting your data. If it's always from a DB, then you must have some way to get the data you need. Sounds like you don't want that DB logic to be within your object. And, you want to be able to call a property on the object which may have to lazy load. That means that at some other time, likely construction, you have to give your object the reference it needs to eventually get the data. That could be a class, a webmethod call, a reference to an interface or whatever you want.

You can get really robust, or you can start simple and refactor later. I'd recommend starting with what you need right now and refactoring to a more general solution later, once you figure out what it is you need.

-ner
 
Back
Top