Вам придется взглянуть на исходный код NHibernate для получения более подробной информации, но я понимаю следующее: отложенная загрузка реализуется путем замены класса прокси-сервером, сгенерированным во время выполнения. Прокси наследуется от класса, так что он может «перехватывать» вызовы методов и лениво загружать реальные данные. Этот перехват будет работать только в том случае, если методы и свойства являются виртуальными, потому что клиентский код вызывает их через ссылку на класс. Клиентский код может не знать о том, что он действительно использует прокси (производный от класса). Фактическая логика отложенной загрузки намного сложнее, но это примерно то, что происходит:
public class Customer {
public virtual String Name {
get { return _name; }
}
}
// code like this gets generated at runtime:
public class CustomerProxy7461293476123947123 : Customer {
private Customer _target;
public override String Name {
get {
if(_target == null){
_target = LoadFromDatabase();
}
return _target.Name;
}
}
}
Таким образом, данные будут загружаться только тогда, когда клиент фактически вызывает «Имя»:
Customer customer = Session.Load<Customer>(1); // <-- proxy is returned
// or
Customer customer = salesman.FavoriteCustomer; // <-- proxy is returned
...
String name = customer.Name; // <-- proxy's Name will be called, loading data
Аналогичные механизмы используются для коллекций, за исключением того, что коллекции не нужно создавать во время выполнения. NHibernate имеет встроенные постоянные коллекции, которые загружают элементы лениво.