2011-01-31 4 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; } 
    } 
} 

보호 집합은 Car 클래스 외부의 읽기 전용 요소입니다. 파트를 채우는 방법이 표시되지 않으므로 List에 채울 수 있도록 "PopulateParts"호출을 후크로 만들었습니다.

+0

"보호 설정은"아니다 파트 컬렉션 속성을 읽기 전용으로 만들 것입니다. 외부 클래스가 다른 컬렉션에 대한 참조를 변경하는 것을 방지합니다. 읽기 전용으로 만들려면 새로운 ReadOnlyCollection (Parts)을 반환하거나 IEnumerable을 반환해야합니다 (진정한 읽기 전용은 아니지만 API 소비자에게 좋은 표시를 제공). 두 가지 방법의 의미에 대한 자세한 내용은 SO 검색을 참조하십시오. – Trygve

+0

아, 그런데 _parts가 멤버 변수 대신 자동 구현 된 속성이라는 것을 알았습니다. 변경해야합니다. – Trygve

관련 문제