2009-06-16 17 views
6

私はいくつかのCodeWarning(ConstructorsShouldNotCallBaseClassVirtualMethods)について疑問に思っていました。私はシンプルなログコレクタークラスを持っており、私はいくつかのオブジェクトを取得するためにNHibernateを使用しています。Nhibernate - リストを初期化する - ベストプラクティス?

私は自分でオブジェクトを作成して、それをHibernateに永続化するために追加します。 リストがNULLでないことを確認する最良の方法は何ですか。

現在、私はこれをやっていますが、「完璧」ではありません。この話題に関するアイデアは?

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>(); 
    } 


} 

答えて

8

LogMessagesは永続化されたものですか?もしそうなら、公的セッターを公開しないことがベストプラクティスです。

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

あなたが注意した場合は、NHibernateのは、プロキシになるオブジェクトを返すと、一般的なリストとそれを交換して、それはときグラグラ行くことになります:あなたがIListのその新しいものと交換し、その後、データベースから盗んと場合NHibernateのは奇妙な取得しますあなたは試して元に戻す。実際

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); 
    } 
} 

、私は、クライアントが> IEnumerableを<取得歩進ん:

は原則として、私は初期化プライベートフィールドを持っているし、クライアントにのみゲッターを公開することを好みますaddのヘルパー関数を追加します。

私implmentationは私がコンストラクタですべての私の初期化を行う以外は同じパターンに従う

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

ようになります。さらに、通常は、addメソッドで親への参照を設定する必要があります。つまり、logMessages.Add(log); log.LogRun = this; –

+2

私はさらに一歩進んで、私のゲッターを読み取り専用のバージョンに戻します... return logMessages.ToList ().AsReadOnly(); – Webjedi

+1

Jamie井出:それは、親を持つ1つの多くの場合、そのヘルパーはそれを設定するのに最適な場所です。それが多対多であれば、親はありません。ここの文脈では分かりませんが、あなたが正しいと大いに疑うでしょう。 Webjedi、あなたのアプローチも気に入っています。それが私がEnumerableで終わった理由です。私の場合、それは私がコレクションでやりたかったことすべてを満足させました。 – Ben

1

私は同じことを行うが、NHibernateはまた、新しいリスト<が作成されますので、私はまた、もパフォーマンスへの影響がどのように大きな疑問>すべてのデフォルトコンストラクタ呼び出しのための...

私たちはだと思います運が良ければ、それはうまくいくでしょう。 NHibernateのはのレイジーロードされたリストを作成することを検討して(私たちはとにかく仮想としてすべてをマークする理由です)LogRunさん:

  1. NHibernateのは
  2. NHibernateのはのプロキシリストを作成しますLogRunを超える反映し、派生クラスを作成します。 LogRun派生クラス
  3. から
  4. あなたがそのプロキシをロードすると、それはしかし、ベース・コンストラクタが最初に呼び出され、それらの派生クラスのいくつかをインスタンス化します - 新しいリスト<を作成する> - それから派生コンストラクタが呼び出されます代わりにプロキシリストを作成します。

実際には使用しないリストを作成しました。

しかし代替案を考えてみましょう:誰もそれを呼び出していない、との代替を行いますように

  • は、コンストラクタは保護されたことを確認します。たとえば、静的なLogRun.GetNew();方法。
  • IList <へのパブリック・セット・アクセスを許可し、新しいオブジェクトを作成するたびに自分で作成します。

正直言って、どちらも非常に乱雑だと思うし、各コンストラクタコールで新しい空のリストを作成する際のパフォーマンス上のオーバーヘッドが限られているので、私は個人的に固執している少なくとも私のプロファイラが私に別のことを教えるまで、P

関連する問題