我的库中的延迟加载或代理模式

时间:2011-06-14 12:23:24

标签: c# reflection proxy loading lazy-evaluation

您好我正在编写一个简单的ORM DLL。该库工作正常,我想添加一些addone - Lazy Loading。 但我不知道如何实现它。我有一个主张。

在我的orm中(我有创建者,但没关系)用户应该创建实现IMapper并设置mapper类的DB类。 有人想到这个。

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>();
}

如果我们有这个类,并设置connectionString,我们可以从DB获取数据。它与Entity Framework非常相似

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

在那一刻,我将检查映射类中的所有属性,如果是虚拟的,则不返回该类,而是返回Lazy Loading类。 我想出了一个概念。不返回(在该示例中)Person类,但是扩展Person类的类,并覆盖所有属性。

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;}
}

用户不应该看到使用该类的任何变化(仅在调试它可能会看到其他类)它应该像魔术一样工作:P

我的问题是: 1.如何实现Lazy Loading in例如Entity Framework,有谁知道? 2.从我的命题更简单的方法?在我的想法中,我必须使用TypeBuilder和Emit与IL源代码 - 我听到它的属性问题 它们不是以正常的方式使用。

2 个答案:

答案 0 :(得分:0)

使用Castle.DynamicProxy(nhibernate使用的相同代理)

答案 1 :(得分:0)

延迟加载是通过在运行时生成继承者并覆盖所有方法来实现的。

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); }
    }
}

代理工厂必须

return new AProxy(custominterceptor);

custominterceptor必须获取您的实体的id,并在第一次使用时实例化A,查询数据库以填充A并将调用委托给A.

必须生成AProxy(使用TypeBuilder在postbuild或运行时)