Is there in the framework . Net, any delayed reading class?

Asked

Viewed 147 times

5

I wonder if in . Net there is some class that allows me to tell her how to read a data, but that DO NOT read immediately... only later when requested, this class reads and stores the value, in case several readings are taken.

Something like:

var delayedDb = DelayedReader.Create(() => LerAlgoDoBancoDeDados());

var resultado = dadoDaMemoria != null ? dadoDaMemoria :
                delayedDb.Read() != null ? delayedDb.Read() :
                null;

To keep me from having to do that:

var dadoDoBanco = LerAlgoDoBancoDeDados();

var resultado = dadoDaMemoria != null ? dadoDaMemoria :
                dadoDoBanco != null ? dadoDoBanco :
                null;

2 answers

5


So, I don’t know this functionality of . NET very well, but doing a search you find the Lazy<T> who does the same work as the Lazy Loading of Entity Framework, but with this you can do the Lazy Loading in their classes.

A article with an example of this.

Good, an example of how to use this class:

public class Proprietario
{
    public int ID { get; set; }
    public string Nome { get; set; }

    public Lazy<IEnumerable<Propriedade>> Propriedades = null;

    public Proprietario()
    {
        this.Propriedades = new Lazy<IEnumerable<Propridade>>();
    }
}

At this time, the owner class is created and with all its properties duly registered, in its builder, the Lazy Loading has been instained and is now ready for use. To use it, you instance the class Proprietário and finally, you do IEnumerable<Propriedade> propriedades = Poprietario.Propriedades.Value.

  • Great article you indicated. Could you bring more information to your answer so that it is more detailed? For example how to use the class Lazy. Thanks! =)

  • 1

    @beta, important you include that this class is only available from version 4 of the framework.

  • So, I was busy here at the company, I answered the basic same, but I will edit the answer with more information.

  • For this particular example, it was necessary to clarify that Propriedades.Value will create a IEnumerable<Propriedade> empty...I mean, without anything else, the default constructor of T in Lazy<T> is invoked. If the default constructor has in you expensive work, then, all right. But usually you see Lazy<T> used with delegate doing expensive work. Using original example: Lazy<Collection<Dados>> DelayedReader = new Lazy<Collection<Dados>>(() => LerAlgoDoBancoDeDados()); Then, the reading (expensive work) happens only in the invocation of DelayedReader.Value

2

As it was said that the class Lazy<T> is available in versions only from . Net 4, here is an implementation for anyone who needs something similar, which is the one I was using earlier, and that works with . Net 2.0 or higher.

This is not a clone of the Lazy class, it’s an implementation of mine. The class mechanism is thread-safe, penalty only on first reading using method Read, or when the method ReadRefresh used. After the first use, it is not possible to discard the internal value of the cache because it is thread-safe... so there is no method ClearCache. To get rid of the cache the variable must be collected by the garbage collector (Garbage-Collector).

public static class Delayed
{
    public static Delayed<T> Create<T>(Delayed<T>.Getter getter)
    {
        return new Delayed<T>(getter);
    }
}

public class Delayed<T>
{
    public delegate T Getter();

    private bool hasValue;
    private T value;
    private Getter getter;

    /// <summary>
    /// </summary>
    /// <param name="getter"></param>
    public Delayed(Getter getter)
    {
        if (getter == null) throw new ArgumentNullException("getter");
        this.getter = getter;
        this.value = default(T);
        this.hasValue = false;
    }

    /// <summary>
    /// Reads the value of the Delayed object, using the value from the cache if available, storing the value in a permanent cache.
    /// </summary>
    public T Read()
    {
        if (!this.hasValue)
        {
            lock (this.getter)
            {
                if (!this.hasValue)
                {
                    this.hasValue = true;
                    this.value = this.getter();
                }
            }
        }

        return this.value;
    }

    /// <summary>
    /// Reads the value of the Delayed object, refreshing the value in a permanent cache.
    /// </summary>
    public T ReadFresh()
    {
        lock (this.getter)
        {
            this.hasValue = true;
            this.value = this.getter();
        }

        return this.value;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.