2013-02-20 15 views
5

私はC#のpojectsのNHibernateを使用しているので、いくつかのモデルクラスがあります。C#で仮想メソッドを呼び出す代わりに

using System; 

namespace TestProject.Model 
{ 
    public class Room 
    { 
     public virtual int Id { get; set; } 
     public virtual string UniqueID { get; set; } 
     public virtual int RoomID { get; set; } 
     public virtual float Area { get; set; } 

    } 
} 

NHibernateのは、これまで正常に動作して、これらのオブジェクトのマッピング:

は、次の例とさせて頂きます。今度は新しいルームオブジェクトを生成したいので、それをデータベースに保存したいと思います。各メンバーを別々に設定しないように、モデルクラスに新しいコンストラクタを追加します。私が書くの仮想メンバーの下 :FxCopのと私のコードを解析

public RoomProperty() 
{ 

} 


public RoomProperty(int pRoomId, int pArea) 
{ 
     UniqueID = Guid.NewGuid().ToString(); 
     RoomID = pRoomId; 
     Area = pArea; 
} 

は私に次のように伝えます:

"ConstructorShouldNotCallVirtualMethodsRule" 
This rule warns the developer if any virtual methods are called in the constructor of a non-sealed type. The problem is that if a derived class overrides the method then that method will be called before the derived constructor has had a chance to run. This makes the code quite fragile. 

This page、これは間違っていると私もそれを理解する理由も説明しています。しかし、私は問題をどのように解決するか分かりません。私は標準のコンストラクタを呼び出した後、データを設定する

私はすべてのコンストラクタを消去し、次のメソッドを追加...

public void SetRoomPropertyData(int pRoomId, int pArea) 
     { 
      UniqueID = Guid.NewGuid().ToString(); 
      RoomID = pRoomId; 
      Area = pArea; 

     } 

.... NHibernateのは、初期化失敗becaue私は私のaplicationを開始傾けます。それは言う:

しかし、私はちょうどコンストラクタで仮想メンバを設定するときと同じようにこのメソッドを仮想に設定することは同じミスです。 これらの間違い(違反)を避けるにはどうすればよいですか?

+0

なぜフィールドに値を設定して建設時のプロパティではないのですか? –

+0

@voroninp NHibernateで簡単にフィールドにアクセスすることはできません – Andrey

+0

私のモデルは実際に約10人のメンバーを持ち、新しいルームオブジェクトqiet​​ iftenを作成するためです。私はそれぞれのプロパティを別々に設定したくありません。 – Metalhead89

答えて

4

問題は仮想セットにあります。ベースクラスのコンストラクタの仮想プロパティに値を渡すと、ベースセットの代わりにオーバーライドされたセットが使用されます。オーバーライドされたセットが派生クラスのデータに依存している場合、派生クラスのコンストラクタはまだ実行されていないため、問題があります。

すべてのサブクラスがオーバーライドされたセット内の状態のデータを使用しない場合は、基本クラスのコンストラクタで仮想プロパティを初期化できます。ドキュメントに適切な警告を追加することを検討してください。

可能であれば、各プロパティのバッキングフィールドを作成してベースクラスコンストラクタで使用してください。

プロパティ初期化を派生クラスに延期することもできます。これを達成するには、派生クラスのコンストラクタで呼び出す基本クラスに初期化メソッドを作成します。

1

は私が仕事に、次のいずれかの期待:

  1. は(限り、NHibernateのは、それをサポートしているとして好ましい)性質が非仮想ください。
  2. 自動実装のプロパティから明示的なバッキングフィールドを持つプロパティに変更し、プロパティを設定する代わりにコンストラクタでフィールドを設定します。
  3. オブジェクトを最初に構築するstatic Createメソッドを作成し、次に、構築されたオブジェクトを返す前にプロパティに値を設定します。

編集:コメントから、オプション3がわかりませんでした。

+0

NHibernateは非仮想プロパティをサポートしていません。 また、createメソッドを静的に設定することもできません。なぜなら、プロパティも静的でなければならないからです(これはうまくいきません)。 – Metalhead89

+0

オプション3を明確にするために私の投稿を編集しました。メソッドは静的ですが、プロパティはそうではありません。 –

+0

オプション3はコンストラクタを保護すると意味があります。したがって、 'Room'のインスタンスを構築する唯一の方法はstaticメソッドです。 –

関連する問題