Reputation: 189
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
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