Внутренние и внешние интерфейсы и коллекции - PullRequest
3 голосов
/ 06 апреля 2009

Как лучше всего реализовать следующее?

У меня есть коллекция объектов, которые реализуют интерфейс, внутренне я хочу иметь возможность выставить set и получить свойства, а получить только извне.

Вот пример того, что я хочу ... Это не компилируется.

public interface ITable
{
   string Name { get; }
}

internal interface IInternalTable 
{
   string Name { get; set; }
}

internal class Table : ITable, IInternalTable
{
   public string Name { get; set; }
   public string ITable.Name { get { return Name; } }
}

public class Database
{
    private List<IInternalTable> tables;

    public List<ITable>
    {
       get { return this.tables; }
    }
}

Ответы [ 5 ]

3 голосов
/ 06 апреля 2009

Используйте это:

public interface ITable
{
    string Name { get; }
}

public class Table : ITable
{
    public string Name { get; internal set; }
}

public class Database
{
    public List<ITable> Tables { get; private set; }
}

Примечание : модификатор доступности, используемый на методе доступа get или set, может только ограничивать видимость, но не увеличивать ее.

1 голос
/ 06 апреля 2009

Если Table реализует IInternalTable неявно, а IInternalTable является внутренним, то эти методы будут доступны только для внутреннего использования (поскольку только внутренний код сможет использовать IInternalTable:

public interface ITable
{
   string Name { get; }
}

internal interface IInternalTable 
{
   string Name { get; set; }
}

public class Table : ITable, IInternalTable
{
   public string Name { get; set; }
   string ITable.Name { get { return Name; } }
}

public class Database
{
    private List<Table> tables;

    public List<Table> Tables
    {
       get { return this.tables; }
    }
}

(Также теперь отображается тип таблицы, чтобы избежать проблем с отсутствием ковариации ..., что также может быть решено с помощью Database.Tables, возвращающей копию и имеющей другое свойство only only.)

0 голосов
/ 06 апреля 2009

На самом деле, я бы рекомендовал полностью скрыть сеттер-интерфейс как частный интерфейс:

public interface ITable
{
   string Name { get; }
}

public class Database
{

    private interface IInternalTable 
    {
       string Name { get; set; }
    }

    private class Table : ITable, IInternalTable
    {
        public string Name { get; set; }
        string ITable.Name { get { return Name; } }
    }

    private List<IInternalTable> tables;

    public List<ITable> Tables
    {
       get { return this.tables; }
    }
}

Таким образом, никто, кроме Database, не может изменять элементы в Database.Tables.

0 голосов
/ 06 апреля 2009

Это обычная потребность, встречающаяся в классах, представляющих модель вашего домена, где вы хотите, чтобы у ваших объектов было открытое для чтения свойство для идентификатора, которое должно быть установлено внутри. Решение, которое я использовал в прошлом, заключается в использовании метода в качестве установщика:

public interface ITable
{
    string Name { get; }
}

internal interface ITableInternal
{
   void SetName(string value);
}

public class Table : ITable, ITableInternal
{
    public string Name { get; }

    public void SetName(string value)
    {
       // Input validation

       this.Name = value;
    }
}

public class Database
{
    public Table CreateTable()
    {
        Table instance = new Table();
        ((ITableInternal)instance).SetName("tableName");

        return table;
    }    
}
0 голосов
/ 06 апреля 2009

Он не скомпилируется, потому что нет преобразования между IInternalTable и ITable. Решение, как предложил Коистья Навин:

public class Table {
    public string Name {get; internal set; }
}

public class Database {
    public IList<Table> Tables { get; private set;}

    public Database(){
        this.Tables = new List<Table>();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...