2011-01-31 10 views
0

コンベンションを使用してパーツのコレクションをマッピングするにはどうすればよいですか?読み取り専用プロパティでアクセスしたコレクションをマップするにはどうすればよいですか?

私はこの大会を試してみましたが、それは常にアンダースコアの接頭辞なしでフィールド名を期待し
public class Part 
{ 
    public virtual int Id { get; set; } 
    public virtual string Name { get; set; } 
} 

public class Car 
{ 
    private readonly List<Part> _parts = new List<Part>(); 

    public virtual int Id { get; set; } 

    public virtual IList<Part> Parts 
    { 
    get { return _parts.AsReadOnly(); } 
    } 
} 

public class HasManyConvention : IHasManyConvention 
{ 
    public void Apply(IOneToManyCollectionInstance instance) 
    { 
    instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore); 
    } 
} 

私は同じ結果と1.2.0.694と2.0.0.698のビルドでそれを試してみました:

"Could not find field 'parts' in class 'TestFluentNHibernate.Car'" 

答えて

0

まず、_partsメンバーを読み取り専用にすることはできません。 NHibernateは値/参照を設定するためにメンバへの書き込みアクセスが必要です。本当に読み取り専用のコレクションをPartsプロパティで返すには、System.Collections.ObjectModel.ReadOnlyCollectionを返す必要があります。これはまた、f.exを返すだけでまだそこにある読み込み/書き込みのコレクション型にあるすべてのメソッドを "削除"します。 list.AsReadOnly()。このようにして返された読み取り専用リストは、コレクションを編集するために.Add()メソッドなどを持っていますが、ランタイム例外が発生するため、ReadOnlyCollectionを最初に返すことはこの可能性を防止するのに最適です。

多くの人は、読み取り専用のIEnumerableを返すのが好きですが、Listや他の読み取り/書き込みのコレクションタイプにキャストしてそのように変更することができます。

外部コードでアイテムを読み取り専用コレクションに追加したり削除したりできるようにするには、AddPartメソッドとRemovePartメソッドを実装する必要があります。

あなたの慣例が正しいに見える私は成功し1.2.0.694とまったく同じ構文を使用しています、私の大会:

 instance.Key.Column(instance.EntityType.Name + "Fk"); 
    instance.Fetch.Subselect(); 
    instance.Inverse(); 
    instance.Cascade.All(); 
    instance.Access.ReadOnlyPropertyThroughCamelCaseField(CamelCasePrefix.Underscore); 

例クラス:

public class Car 
{ 
    private List<Part> _parts; 

    public Car() 
    { 
     // Initialize member collection _parts 
     _parts = new List<Part>(); 
    } 

    public virtual int Id { get; set; } 

    // Return readonlycollection here, ReadOnlyCollection implements 
    // IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable, 
    // so the returned list can be any collection type inheriting from these base types. 
    public ReadOnlyCollection<Part> Parts 
    { 
     get { return new List<Part>(_parts).AsReadOnly(); } } 
    } 

    public AddPart(Part part) 
    { 
     // Usually I don't want duplicates 
     if (!_parts.Contains(part)) 
      _parts.Add(part); 
    } 
} 
0

うまくいけば、これが役に立ちます。試してみてください...

public class Car 
{ 
    protected virtual List<Part> _parts { get;set; } 

    public Car() 
    { 
    // Initialize "Parts" to not be null 
    this.Parts = new List<Part>(); 
    } 
    public void PopulateParts (int someID) 
    { 
    // Do a call out to one of your helpers to populate "Parts" 
    // so it can be used. 
    //this.Parts = SomeCall(someID); 
    } 

    public virtual int Id { get; set; } 

    public virtual IList<Part> Parts 
    { 
    get { return this._parts; } // No need for "ReadOnly" since "protected set" will prevent changes outside of this class. 
    protected set { this._parts = value; } 
    } 
} 

保護されたセットは、このクラスを車外の読み取り専用要素にします。 パーツをどのように埋め込むのかわからないので、Listにデータを入れるために、 "PopulateParts"という呼び出しをフックとして作成しました。

+0

"保護されたセットが" ではありませんPartsコレクションのプロパティを読み取り専用にします。外部クラスが別のコレクションへの参照を変更するのを防ぐだけです。読み取り専用にするには、新しいReadOnlyCollection(Parts)を返すか、IEnumerableを返します(本当に読み取り専用ではありませんが、APIコンシューマーには良い指示を与えます)。両方の方法の意味について詳しくは、SOを検索してください。これについては多数のスレッドがあります。 – Trygve

+0

ところで、ちょうど_partsがメンバ変数の代わりに自動実装されたプロパティであることがわかりました。変更する必要があります – Trygve

関連する問題