Осведомленность базового класса об изменениях свойств в производных классах - PullRequest
3 голосов
/ 22 декабря 2009

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

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

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

Ответы [ 3 ]

3 голосов
/ 22 декабря 2009

Можете ли вы заставить производные классы реализовать INotifyPropertyChanged? В этом случае я бы добавил слушателя события PropertyChanged в базовый класс constructur и chill. Производный класс теперь все еще должен следовать шаблону (что может быть чем-то, чего вы хотите избежать?).

Хорошее чтение для подхода "без буквальных строк" для вызова событий, изменяющих свойство: http://monotorrent.blogspot.com/2009/12/yet-another-inotifypropertychanged-with_06.html

1 голос
/ 22 декабря 2009

Подходящим шаблоном для управления доступом к классу (или набору классов) является шаблон Proxy. Этот шаблон позволит вам реализовать правильное поведение isDirty один раз на уровне прокси и делегировать любое поведение только для чтения реальному экземпляру без изменений.

Этот шаблон наиболее эффективен при использовании с шаблоном Factory для управления созданием экземпляров.

Это решение замаскирует тип времени выполнения экземпляра, поэтому, если ваш проект опирается на информацию о типе времени выполнения, вам нужно либо решить эту проблему отдельно (например, с помощью шаблона State), либо найти альтернативный подход.

0 голосов
/ 22 декабря 2009

(Quick & Dirty) - Как насчет этого? (Ваша реализация GetHashCode может отличаться - я использовал ReSharper для ее автоматической генерации)

    public abstract class Animal
    {
        private int _originalHash;

        public string Name { get; set; }
        public int Age { get; set; }

        public Animal(string name, int age)
        {
            this.Name = name;
            this.Age = age;

            this._originalHash = GetHashCode();
        }


        public override sealed int GetHashCode()
        {
            unchecked
            {
                return ((Name != null ? Name.GetHashCode() : 0) * 397) ^ Age;
            }
        }

        public bool IsDirty
        {
            get
            {
                return this._originalHash != GetHashCode();
            }
        }
    }

    public class Cat : Animal
    {
        public Cat(string name, int age)
            : base(name, age)
        {
        }
    }

Использовал это для проверки ...

var cat = new Cat("BobTheCat", 12);
Console.WriteLine(cat.IsDirty);
cat.Age = 13;
Console.WriteLine(cat.IsDirty);

Результаты были:

Ложная Правда

...