Использование явных интерфейсов для предотвращения случайного изменения свойств в C # - PullRequest
2 голосов
/ 11 ноября 2009

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

Например,

 virtual public DateTime CreatedOn { get; protected set; }
 virtual public DateTime? ModifiedOn { get; protected set; }
 #region IHaveUpdateDateFields Members

 DateTime IHaveUpdateDateFields.CreatedOn
 {
    get
    {
        return this.CreatedOn;
    }
    set
    {
        this.CreatedOn = value;
    }
}

DateTime? IHaveUpdateDateFields.ModifiedOn
{
    get
    {
        return this.ModifiedOn;
    }
    set
    {
        this.ModifiedOn = value;
    }
}

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

Мои вопросы:

  1. Я полагаюсь на определенное поведение или я гарантирую, что все компиляторы C # будут разрешать методы таким образом? Я не хочу обнаруживать, что стандарт C # говорит, что такого рода разрешение методов не определено, а затем случайно получаю ужасное переполнение стека при сборке, например, для Mono.
  2. Есть ли более хороший (в идеале более крутой) способ сделать это? У меня мог бы быть безопасный для ModelBinder интерфейс, который я передаю своему контроллеру, но, похоже, это не спасло бы меня от кода, и я не думаю, что он обеспечил бы столь же прозрачный подход минимизации случайного изменения свойств.

1 Ответ

3 голосов
/ 11 ноября 2009

Это прекрасно определено; явные реализации интерфейса имеют приоритет при использовании интерфейса, а обычное свойство вступает в силу в противном случае (в том числе из тела get / set).

Что касается того, чтобы сделать его более аккуратным ... лучшее, что я могу предложить, - это переформатировать его, чтобы сделать его менее многословным ...

DateTime IHaveUpdateDateFields.CreatedOn
{
    get { return CreatedOn; }
    set { CreatedOn = value; }
}

(обратите внимание также, что this является неявным и избыточным)

В качестве отступления - безопасность - это только удобство, а не гарантия ... внешние абоненты все еще могут использовать ваш интерфейс и обычно (ab) могут использовать отражение, чтобы прыгать через простые вещи, такие как protected - или даже просто установить поля непосредственно.

...