Исключение NHibernate: метод Add должен быть публичным или защищенным виртуальным или защищенным внутренним виртуальным - PullRequest
9 голосов
/ 17 февраля 2010

Взять этот класс в качестве примера:

public class Category : PersistentObject<int>
{
    public virtual string Title { get; set; }
    public virtual string Alias { get; set; }

    public virtual Category ParentCategory { get; set; }
    public virtual ISet<Category> ChildCategories { get; set; }


    public /*virtual*/ void Add(Category child)
    {
        if (child != null)
        {
            child.ParentCategory = this;
            ChildCategories.Add(child);
        }
    }
}

При запуске приложения без виртуального ключевого слова метода add я получаю эту ошибку:

method Add should be 'public/protected virtual' or 'protected internal virtual'

Я понимаю, почему свойства должны быть объявлены как виртуальные, потому что они должны быть переопределены функцией отложенной загрузки.

Но я не понимаю, почему Методы должны быть объявлены как виртуальные ... они должны быть переопределены по какой причине?

Это очень запутанно!

Ответы [ 2 ]

10 голосов
/ 22 марта 2010

Методы также должны быть виртуальными, поскольку они могут обращаться к полям. Рассмотрим следующую ситуацию:

class Entity
{

  //...
  private int a;
  public virtual int A 
  { 
     get { return a; }
  }

  public virtual void Foo()
  {
    // lazy loading is implemented here by the proxy
    // to make the value of a available
    if (a > 7) 
    // ...
  }
}
4 голосов
/ 17 февраля 2010

Я считаю, что это требуется для функции отложенной загрузки в NHibernate, где NHibernate создает прокси вашей сущности и контролирует весь доступ к ней. Вот почему каждый метод и свойство должны быть виртуальными. По сути, если есть член, который что-то делает с сущностью, NH должен знать об этом и подключиться к нему. Как упоминалось ранее, для того, чтобы NHibernate выполнял «магию», он создает прокси-классы, которые наследуются от ваших сущностей (в вашем случае Category). Однако, если вы заставите ваши сущности реализовать интерфейс, он будет использовать этот интерфейс для создания прокси вместо конкретных типов. Таким образом, вам не придется отмечать все виртуально.

РЕДАКТИРОВАТЬ: Некоторые исправления ... Согласно this , я вынужден сказать, что кажется, что NH на самом деле ничего не делает с виртуальными методами, в конце концов. И я даже читал, как кто-то говорил, что они убрали эту проверку времени выполнения из сборки ядра NH, чтобы обойти это. Я предполагаю, что это старые требования, которые не были удалены. Круто то, что похоже, что есть инициатива использовать PostSharp для статических прокси, поэтому вашим классам не нужно будет объявлять что-либо виртуальное, чтобы NH генерировал прокси. Плохо то, что, похоже, он застрял в ветке почти два года.

...