Интерфейс C # с внутренними сеттерами - PullRequest
1 голос
/ 12 января 2012

Фон : Изобразите художественное произведение формы, в которой есть несколько уровней вложенных фигур. Изменение свойств, например Площадь и длина любой из этих фигур внутри фигуры приведут к изменению всех связанных свойств и форм.

У меня есть шаблон дизайна, который выглядит так:

У меня есть объектный граф, называемый (для обсуждения) "NestedShapes", который имеет множество свойств, связанных друг с другом, например, "Площадь" и "Длина". Но график спроектирован так, чтобы быть тупым, то есть с учетом любого значения он не знает, как рассчитать другое, и не будет этого делать.

Вместо этого граф может быть присоединен к GraphManager, который берет в своем конструкторе корневой узел верхнего уровня IRootShape.

NestedShapes реализует IRootShape, который также реализует INotifyPropertyChanged. GraphManager подписывается на эти изменения свойств и запускает логику для вычисления связанных полей и установки графика в правильное состояние с помощью IRootShape.

Задача : Наряду с IRootShape у меня есть IShape, ISquare, ICircle и т. Д., Которые являются реальными интерфейсами C #. Но проблема в том, что для некоторых из этих свойств я хочу, чтобы у них были только сеттеры, которые являются частными для GraphManager. Я знаю, что реализующая форма все еще может предоставлять общедоступный установщик, но я не хочу, чтобы обязательно представлял их на стороне пользовательского интерфейса, чтобы иметь возможность установить свойство из GraphManager. Что я должен делать? Базовые классы с внутренним набором пути?

Ответы [ 2 ]

2 голосов
/ 12 января 2012

Пусть GraphManager взаимодействует с базовыми классами.

Все остальное взаимодействует только с интерфейсами.

Не открывайте свойства в вашем интерфейсе.

public class Circle : ICircle{
   public double Radius{
      get;set;
   }

   /* blah blah ... */
}

public interface ICircle {
   /* No properties */

   /* blah blah ...*/
}
1 голос
/ 07 февраля 2017

Уловка, чтобы сделать это через интерфейсы, состоит в том, чтобы использовать два отдельных интерфейса; один публичный, а второй только внутренний. Да, для этого требуется немного больше кода, поскольку вам нужно явно реализовать внутренний интерфейс, вручную делегируя его свойства в соответствии с фактическими свойствами, но я просто скрываю это в частичном классе в файле с именем «ClassName.Internal.cs» *. 1001 *

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

Вот пример TestItem с общедоступными и внутренними сеттерами, доступными через интерфейсы.

Вот файл основного класса с открытым интерфейсом, хранящийся в TestItem.cs

public interface ITestItem
{
    ModelItem  Owner { get; }
    ModelScope Scope { get; }
}

public partial class TestItem : ITestItem
{
    // These implicitly handle ITestItem since the getters are public
    public ModelItem  Owner { get; internal set; }
    public ModelScope Scope { get; internal set; }
}

Вот внутренняя реализация, сохраненная в TestItem.Internal.cs, реализованная через частичный класс.

internal interface IWritableTestItem
{
    ModelItem  Owner { get; set; }
    ModelScope Scope { get; set; }
}

public partial class TestItem : IWritableTestItem
{
    ModelItem IWritableTestItem.Owner
    {
        get => Owner;
        set => Owner = value;
    }

    ModelScope IWritableTestItem.Scope
    {
        get => Scope;
        set => Scope = value;
    }
}

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...