Ленивая загрузка или шаблон прокси в моей библиотеке - PullRequest
1 голос
/ 14 июня 2011

Привет, я пишу простую ORM DLL. Библиотека работает нормально, и я хотел бы добавить некоторые дополнения - Ленивая загрузка. Но я не знаю, как это реализовать. У меня есть одно предложение.

В моем orm (у меня есть создатель, но я не против), пользователь должен создать класс DB, который реализует IMapper и установить класс mapper. Подумайте об этом.

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, мы можем взять данные из БД. Это очень похоже на Entity Framework

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

В этот момент я проверю все свойства в классе сопоставления и, если они виртуальные, то вернет не тот класс, а класс отложенной загрузки. Я придумываю одну концепцию. Не возвращать (в этом примере) класс 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, например, в Entity Framework? 2. Есть ли более простой способ из моего предложения? По моей идее, я должен использовать TypeBuilder и Emit с исходным кодом IL - я слышал, что это проблемы со свойствами они не используются обычным способом.

Ответы [ 2 ]

0 голосов
/ 14 января 2015

Ленивая загрузка реализуется путем генерации наследника во время выполнения и переопределения всех методов.

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 должен взять идентификатор вашей сущности и при первом использовании создать экземпляр A, запросить базу данных для заполнения A и делегировать вызов A.

Необходимо сгенерировать AProxy (после сборки или во время выполнения с использованием TypeBuilder)

0 голосов
/ 14 июня 2011

Использовать Castle.DynamicProxy (тот же прокси, что и nhibernate)

...