2009-06-16 10 views
6

Właśnie się zastanawiałem nad niektórymi CodeWarning (ConstructorsShouldNotCallBaseClassVirtualMethods), a jeśli istnieje lepszy sposób to zrobić. Mam proste klasy kolekcjonowania dziennika i używam NHibernate do pobierania niektórych obiektów.Nhibernate - Inicjuj listy - najlepsze praktyki?

Czasami samodzielnie tworzę obiekty i dodam je do NHibernate w celu zachowania równowagi. Jaki jest najlepszy sposób, aby upewnić się, że listy nigdy nie są NULL.

Obecnie robię to, ale nie wydaje się "idealne". Masz pomysł na ten temat?

public class LogRun 
{ 
    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; } 
    public virtual IList<Log> LogMessages { get; set; } 
    public virtual int LogMessageCount { get { return LogMessages.Count; } } 

    public LogRun() 
    { 
     LogMessages = new List<Log>(); 
    } 


} 

Odpowiedz

8

Czy LogMessages to uporczywa rzecz? Jeśli tak, najlepiej jest nigdy nie wystawiać publicznego setera. NHibernate dostaje dziwne jeśli retreive z bazy danych, a następnie zastąpić że IList na nową:

var myLog = session.Get<LogRun>(1); 
Assert.True(myLog.LogMessages.Count > 0); 
myLog.LogMessages = new List<Log>(); 

Jeśli pamiętać, NHibernate jest zwrócenie proxy obiekt i zastąpienie go z listy rodzajowy spowoduje to pójść wonky kiedy próbujesz i oszczędzasz.

Z reguły wolę dysponują pole, które zainicjować, a następnie wystawiać tylko getter do klienta:

public class LogRun 
{ 
    private IList<Log> logMessages = new List<Log>(); 

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; } 
    public virtual IList<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count; } } 

    public void AddLogMessage(Log log) 
    { 
     logMessages.Add(log); 
    } 
} 

Właściwie pójść o krok dalej, klient dostaje IEnumerable <> i dodaję funkcję pomocnika dla dodania.

Moja implmentation wyglądałby

public class LogRun 
{ 
    private IList<Log> logMessages = new List<Log>(); 

    public virtual int Id { get; private set; } 
    public virtual DateTime StartTime { get; set; } 
    public virtual DateTime EndTime { get; set; } 
    public virtual IEnumerable<Log> LogMessages { get { return logMessages; } } 
    public virtual int LogMessageCount { get { return LogMessages.Count(); } } 

    public void AddLogMessage(Log log) 
    { 
     logMessages.Add(log); 
    } 
} 
+2

śledzę ten sam wzór z wyjątkiem zrobić całe inicjalizacji w konstruktorze. Ponadto zazwyczaj konieczne jest ustawienie odwołania do elementu nadrzędnego w metodzie dodawania, np. LogMessages.Add (log); log.LogRun = this; –

+2

Poszedłem o krok dalej i sprawiłem, że mój getter zwróci wersję tylko do odczytu ... return logMessages.ToList () .AsReadOnly(); – Webjedi

+1

Jamie Ide: Prawda, jeśli jest to jeden-wielu z rodzicem, to ten pomocnik jest świetnym miejscem do ustawienia. Jeśli jest to wiele dla wielu, to nie ma rodzica. Nie jestem pewien w kontekście, ale podejrzewam, że masz rację. Webjedi, podoba mi się również Twoje podejście. Dlatego znalazłem się w Enumerable. W moim przypadku spełnił on wszystko, co chciałem zrobić z kolekcją. – Ben

1

zrobić to samo, ale ja też zastanawiam się, jak duży wpływ ma perfomance, ponieważ NHibernate będzie również utworzyć nową listę <> dla każdego wywołania konstruktora domyślnego ..

Myślę, że jesteśmy na szczęście i że to zadziała. Rozważmy NHibernate tworząc leniwy załadowane listę LogRun (który jest dlaczego zaznaczamy wszystko jako wirtualny tak):

  1. NHibernate będzie odzwierciedlać nad LogRun i utworzyć klasę pochodną
  2. NHibernate uczyni proxy listę takich Klasa LogRun pochodzące
  3. -
  4. Po załadowaniu tego pełnomocnictwa, to wystąpienia niektórych z tych klas pochodnych, jednak baza-konstruktor nazywa pierwsza - tworzenie nowej listy <> - wówczas konstruktor pochodzi nazywa , zamiast tego tworzy się listę proxy.

W efekcie stworzyliśmy listę, z której nigdy nie skorzystamy.

Rozważmy alternatywy choć:

  • Bądź chroniony konstruktor, tak że nikt nie będzie go wywołać i zrobić alternatywę. Na przykład statyczny LogRun.GetNew(); metoda.
  • Zezwól na publiczny dostęp do zestawu IList <> i twórz go samodzielnie za każdym razem, gdy tworzysz nowy obiekt.

Szczerze mówiąc, myślę, że oba są bardzo brudny, a ponieważ jestem (dość), czy narzut perfomance na tworzeniu nowej listy pusty każdego konstruktora-rozmowy jest ograniczony, to co ja osobiście trzymać zbyt do tej pory ... Cóż, przynajmniej do momentu, gdy mój profiler powie mi inaczej: P