2009-01-21 11 views
19

przyjrzeć tym przykładzie kodu:Czy można wywoływać właściwości wirtualne z konstruktora jednostki NHibernate?

public class Comment 
{ 
    private Comment() 
    { } 

    public Comment(string text, DateTime creationDate, string authorEmail) 
    { 
     Text = text; 
     CreationDate = creationDate; 
     AuthorEmail = authorEmail; 
    } 

    public virtual string Text { get; private set; } 
    public virtual DateTime CreationDate { get; set; } 
    public virtual string AuthorEmail { get; private set; } 
} 

wiem, że jest uważany złą praktyką wywołać funkcje członków wirtualnych z konstruktora, jednak w NHibernate muszę właściwości jako wirtualny wspierać leniwy załadunku. Czy w tym przypadku jest to uważane za OK?

+1

Myślę, że kwestia zasługuje na więcej Uwaga i chciałbym dodać ten odnośnik: http://stackoverflow.com/search?q=nhibernate+virtual+constructor Myślę, że dodanie metody Initialize() lub konstruktora less mniejszego parametru zmienia projekt w celu dostosowania do ramy prawne - co według mnie jest złą praktyką; może chcesz, aby twój obiekt był cały czas ważny (myślę, że powinieneś) ... Inicjowanie() metod/konstruktorów mniejszych parametrów pozwala konstruować obiekty bez ich potrzeby. – W3Max

Odpowiedz

5

Jestem prawie pewien, że to dobrze, ale jeśli martwisz się, zawsze możesz po prostu przypisać właściwości po parametrze mniej wywołania konstruktora.

0

wiem, że FxCop narzeka jeśli wywołać metodę wirtualną w konstruktorze, ale nie wiem co FxCop mówi czy dzwonisz właściwość wirtualny w swoim konstruktorze ...
myślę, że FxCop będzie narzekają również, ponieważ właściwość jest tłumaczona na metodę w IL.

Możesz również utworzyć swoje właściwości jako "nie-wirtualne", a po prostu wpisz "lazy = false" w swoim "mapowaniu klas" w NHIbernate. Nie wpłynie to na zachowanie leniwego obciążenia kolekcji.

(robię to cały czas, ponieważ nie podoba mi się, że moja infrastruktura (NHibernate) wymaga mnie mieć właściwości wirtualny.
Ja też nie wiem, czy korzyści z posiadania wydajność dynamicznych proxy jest w NHibernate znaczący).

0

Myślę, że nie powinieneś wywoływać tego w konstruktorze. Możesz podać metodę Initialize(), którą możesz wywołać po skonstruowaniu obiektu.

W Initialize() można wywołać wymaganych metod wirtualnych

1

Jest OK w tej próbce, ale może to spowodować problemy podczas dziedziczyć klasę i nadpisać właściwości. Ogólnie można lepiej tworzyć pola dla właściwości wirtualnych.

2

Aby rozwinąć na Paco odpowiedź:

w większości przypadków to nie boli. Ale jeśli klasa jest dziedziczona, wirtualna pozwala na przesłonięcie właściwości/ustawienia, tak więc zachowanie nie jest już w pełni obudowane i kontrolowane, więc teoretycznie może się zepsuć. FxCop ostrzega o tym, ponieważ jest to potencjalny problem.

Celem FxCop jest ostrzeganie o potencjalnych problemach. Nie jest to konieczne, aby używać właściwości w konstruktorze, jeśli wiesz, kto/co kiedykolwiek będzie dziedziczyć po klasie, ale nie jest to oficjalnie "najlepsza praktyka".

Tak więc odpowiedź brzmi, że wszystko jest w porządku, o ile kontrolujesz dziedziczenie klasy. W przeciwnym razie nie używaj go i bezpośrednio ustaw wartości pól. (Co oznacza, że ​​nie możesz używać automatycznych właściwości pobierania/ustawiania C# 3.0 - musisz samemu zapisać pola zawijania właściwości.)

Uwaga: Osobiście wszystkie moje projekty to witryny internetowe, które hostujemy dla klientów . Zakładając, że ta konfiguracja pozostanie niezmieniona dla projektu, warto zrezygnować z konieczności duplikowania różnych sprawdzeń zerowych/argumentów. Ale w każdym innym przypadku, w którym nie jestem pewien, czy zachowamy pełną kontrolę nad projektem i używaniem klasy, nie skorzystam z tego skrótu.

0

IMHO najlepiej praktyką jest korzystanie z pól właściwości Podłoże:

public class Comment 
{ 
    private DateTime _creationDate; 
    private string _text; 
    private string _authorEmail; 
    private Comment() { } 
    public Comment(string text, DateTime creationDate, string authorEmail) 
    { 
     _text = text; 
     _creationDate = creationDate; 
     _authorEmail = authorEmail; 
    } 
    public virtual string Text 
    { 
     get { return _text; } 
     private set { _text = value; } 
    } 
    public virtual string AuthorEmail 
    { 
     get { return _authorEmail; } 
     private set { _authorEmail = value; } 
    } 
    public virtual DateTime CreationDate 
    { 
     get { return _creationDate; } 
     set { _creationDate = value; } 
    } 
} 

Więc można uniknąć problemów w klasach potomnych i nie widać żadnego ostrzeżenia już

Powiązane problemy