2011-01-31 2 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, который также доступен только для чтения, но его можно отнести к списку или другому типу коллекции чтения и записи и изменить его.

Вы должны реализовать методы 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. Поскольку я не вижу, как вы собираетесь заполнять детали, я создал вызов «PopulateParts» как крючок, чтобы вы могли заполнить список.

+0

"защищенный набор" не сделав свойство коллекции деталей доступным только для чтения. Это позволяет запретить внешним классам изменять ссылку на другую коллекцию. Чтобы сделать его доступным только для чтения, вам нужно вернуть новый ReadOnlyCollection (Parts) или вернуть IEnumerable (не по-настоящему доступный только для чтения, но дает хорошие указания потребителям API). Для получения дополнительной информации о последствиях обоих способов выполните поиск SO, в этом есть множество потоков. – Trygve

+0

Ой, кстати, только что понял, что ваш _parts является автоматически реализованным свойством, а не переменной-членом ... это должно быть изменено – Trygve

Смежные вопросы