adamowski
adamowski

Reputation: 189

Lazy loading or proxy pattern in my library

Hi i'm writing a simple ORM DLL. The library works fine and i would like add some addone - Lazy Loading. But i don't know how to implements that. I have one proposition.

In my orm (i have creator but never mind) User should create DB class who implements IMapper and set mapper class. Somethink linke this.

public class Person
{
  public virtual string Name {get;set;}
  public virtual int Age {get; set;}
}

public class DataBase : IMapper
{
  MapperSet<Person> Persons = new MapperSet<Person>();
}

If we have that class, and setup connectionString, we can take the data from DB. It's very similar to Entity Framework

Person p = Persons.Single(x=>x.Name == "John");

In that moment, i will check the all properties in mapping class and if are virtual then not return a that class, but Lazy Loading class. I think out one conception. Not return (in that example) Person class but the class who extends Person class, and override all properties.

public class PersonReturn : Person
{
  //here i must create a method who really take the data from db
  private string Query = "SELECT TOP(1) FROM Person WHERE Name = 'John'";
  private Execute()
  {
    p = (Person)Db.TableToObject(Query);
  }
  Person p;

  public override string Name 
  {
   get
   {
     if(p == null)
      p = Execute();

    return p.Name;
   }
   set {}
   }

  //same
  public override int Age {get; set;}
}

User shouldn't see any change with using that class (only in debug it maybe see other class) it's should work as magic :P

My questions are : 1. How is implement Lazy Loading in for example Entity Framework, anybody know ? 2. Is simpler way from my proposition ? In my idea i must use TypeBuilder and Emit with IL source code - i hear it's problems with properties they aren't be use in normaly way.

Upvotes: 2

Views: 2230

Answers (2)

Teter28
Teter28

Reputation: 524

Lazy loading is implemented by generating inheritor at runtime and override all methods.

public class A
{
    virtual protected string name { get; set; }
}

public interface IInterceptor
{
    object Invoke(MethodInfo method, params object[] arguments);
}

public sealed class AProxy : A
{
    static private readonly MethodInfo getname = typeof(A).GetProperty("name", ...).GetGetMethod(true);
    static private readonly MethodInfo setname = typeof(A).GetProperty("name", ...).GetSetMethod(true);

    private readonly IInterceptor interceptor;

    public AProxy(IInterceptor interceptor)
    {
        this.interceptor = interceptor;
    }

    override protected string name
    {
        get { return this.interceptor.Invoke(AProxy.getname); }
        set { this.interceptor.Invoke(AProxy.setname, value); }
    }
}

Proxy factory have to to

return new AProxy(custominterceptor);

custominterceptor must take id of your entity and in first usage instantiate A, query database to populate A and delegate call to A.

AProxy must be generated (postbuild or at runtime using TypeBuilder)

Upvotes: 0

jgauffin
jgauffin

Reputation: 101192

Use Castle.DynamicProxy (same proxy that nhibernate uses)

Upvotes: 1

Related Questions