C # - Сделать поля / свойства только для чтения условно - PullRequest
6 голосов
/ 08 апреля 2010

у меня три класса; Классы A и B оба относятся к эталонному классу C.

Как сделать так, чтобы члены класса C могли быть изменены при ссылке на класс A, но не изменены при ссылке на класс B?

IE, должно быть возможно следующее:

classA myClassA = new classA();
myClassA.myClassC.IssueNumber = 3;

Но это не должно быть возможно;

classB myClassB = new classB();
myClassB.myClassC.IssueNumber = 3;

Настройка classB.classC только для чтения позволяет изменять свойства classC.

Я уверен, что это основные вещи, но не могу найти простой ответ.

Спасибо, A

Ответы [ 6 ]

17 голосов
/ 08 апреля 2010

Шаблон 1: создание простого интерфейса только для чтения IRead. Сделайте простой интерфейс записи IWrite. Сделайте интерфейс чтения-записи IReadWrite : IRead, IWrite. Реализация classC : IReadWrite. Объявите myClassA.myClassC как IReadWrite. Объявите myClassB.myClassC как IRead. (Вам не нужно никому вводить IWrite, если вам это не нужно: -))

Шаблон 2: создайте оболочку только для чтения для classC с именем ReadOnlyClassC и используйте ее в classB.

Шаблон 1 используется потоками ввода-вывода для разделения реализаций считывателя и записывающего устройства, а затем объединяет их в потоки чтения-записи.

Шаблон 2 используется общими коллекциями для предоставления фасета только для чтения.

3 голосов
/ 08 апреля 2010

Я предлагаю вам разделить класс C на 2 класса:

class C
{
    protected int _IssueNumber;

    public int GetIssueNumber()
    {
        return _IssueNumber;
    }
}

class WritableC : C
{
    public void SetIssueNumber(int issueNumber)
    {
        _IssueNumber = issueNumber;
    }
}

class A
{
    public WritableC myClassC;
    ...
}

class B
{
    public C myClassC;
    ...
}

EDIT:

Как сказал Мартиньо Фернандес , вы также можете использовать один класс с 2 различными интерфейсами:

interface IC
{
    int IssueNumber { get; }
}

interface IWritableC : IC
{
    int IssueNumber { get; set; }
}

class C : IWritableC
{
    protected int _IssueNumber;

    public IssueNumber
    {
        get { return _IssueNumber; }
        set { _IssueNumber = value; }
    }
}

class A
{
    public IWritableC myClassC;
    ...
}

class B
{
    public IC myClassC;
    ...
}
3 голосов
/ 08 апреля 2010

Вы не можете сделать это в C #, как в C ++.Но вы можете определить интерфейс только для чтения для класса C, который будет обрабатываться B, тогда как A будет обрабатывать фактический C.

2 голосов
/ 08 апреля 2010

Вы не можете назначать права как таковые определенным классам. Однако вы можете поместить класс A и класс C в одну сборку, а класс B - в другую. Затем определите метод доступа set для свойства как internal. Это означает, что он может быть установлен только классами в одной сборке:

public int IssueNumber
{
  get;
  internal set;
}

В качестве альтернативы вы можете реализовать метод для класса A, который устанавливает значение свойства, но не для класса B:

public void SetIssueNumber(int value)
{
  this.myClassA.IssueNumber = value;
}
1 голос
/ 08 апреля 2010

Если это так важно, создайте интерфейс:

// read only interface
interface IC
{
  int IssueNumber { get; }
}

class C : IC
{
  int IssueNumber { get; set; }
}

// get the full type from A
class A
{
  C MyClassC { get; }
}

// only get read only interface from B
class B
{
  IC MyClassC { get; }
}
1 голос
/ 08 апреля 2010

имеет логическое значение isReadOnly только в ClassC. Установите это логическое значение с помощью конструктора. При создании экземпляра ClassC в ClassB вызовите ClassC myClassC = new ClassC(true); В блоке набора IssueNumber проверьте логическое значение. Если true, измените значение

bool isReadOnly;
public ClassC(bool isReadOnly)
{
    this.isReadOnly = isReadOnly;
}

int _issueNumber;
public int IssueNumber
{
    get
    {
        return _issueNumber;
    }
    set
    {
        if(!isReadOnly)
        {
            _issueNumber = value;
        }
    }
}
...