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开发者_JS百科;
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.
Use Castle.DynamicProxy (same proxy that nhibernate uses)
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)
精彩评论