свойства c # с повторным кодом - PullRequest
5 голосов
/ 15 сентября 2008

У меня есть класс с кучей свойств, которые выглядят так:

public string Name
{
    get { return _name; }
    set { IsDirty = true; _name = value; }
}

Было бы намного проще, если бы я мог положиться на C # 3.0, чтобы сгенерировать резервное хранилище для них, но есть ли способ выделить IsDirty = true; так что я могу написать свои свойства примерно так и при этом вести себя так же:

[MakesDirty]
public string Name { get; set; }

Ответы [ 10 ]

5 голосов
/ 15 сентября 2008

Нет. Не без написания значительно большего (загадочного?) Кода, чем в исходной версии (вам нужно было бы использовать отражение, чтобы проверить атрибут в свойстве, а что нет .. я упоминал, что он «медленнее») .. Это это тот тип дублирования, с которым я могу жить.

MS также нуждается в вызове событий при изменении свойства . INotifyPropertyChanged, который является жизненно важным интерфейсом для уведомлений об изменениях. Каждую реализацию я уже видел делает

set
{ 
  _name = value; 
  NotifyPropertyChanged("Name"); 
}

Если бы это было возможно, я бы подумал, что у этих умных парней из MS уже будет что-то подобное ..

3 голосов
/ 15 сентября 2008

Если вы действительно хотите пойти по этому пути, чтобы изменить то, что код делает с помощью атрибута, есть несколько способов сделать это, и все они связаны с AOP (Аспектно-ориентированным программированием). Проверьте PostSharp , который является посткомпилятором, который может изменить ваш код на этапе после компиляции. Например, вы можете установить один пользовательский атрибут для ваших свойств (или аспект, как он называется в AOP), который внедряет код в установщики свойств, который помечает ваши объекты как грязные. Если вам нужны примеры того, как этого добиться, вы можете посмотреть их руководства .

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

Существует больше платформ AOP, некоторые из которых используют посткомпиляцию, а некоторые используют механизмы перехвата методов, которые присутствуют в .Net, у последних есть некоторые недостатки производительности по сравнению с первой.

3 голосов
/ 15 сентября 2008

Вы можете попробовать настроить фрагмент кода, чтобы упростить его создание.

2 голосов
/ 15 сентября 2008

Нет, когда вы используете автоматические свойства, вы не можете контролировать реализацию. Наилучшим вариантом является использование инструмента шаблонов, фрагментов кода или создание частного SetValue <T> (ref T backingField, T value), который инкапсулирует логику установщика.

private void SetValue<T>(ref T backingField, T value)
{
   if (backingField != value)
   {
      backingField = value;
      IsDirty = true;
   }
}

public string Name
{
   get
   {
      return _name;
   }
   set
   {
      SetValue(ref _name, value);
   }
}
0 голосов
/ 15 сентября 2008

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

В противном случае, вы смотрите на использование, возможно, событий. Вам все равно придется добавлять событие к каждому методу набора, но выгода будет в том, что вы не будете жестко программировать, что делать с грязными наборами в каждом свойстве, и сможете контролировать в одном месте, что нужно делать. Это, по крайней мере, введет немного больше повторного использования кода.

0 голосов
/ 15 сентября 2008

Я бы сказал, что лучшим способом решения этой проблемы является использование Аспектно-ориентированного программирования (АОП) Матс Хеландер написал об этом в InfoQ . Статья немного грязная, но за ней можно следить. Существует ряд различных продуктов, которые используют AOP в .NET-пространстве, я рекомендую PostSharp.

0 голосов
/ 15 сентября 2008

Существует свойство DefaultValueAttribute, которое можно назначить свойству, оно в основном используется инструментами конструктора, чтобы они могли указывать, когда свойство было изменено, но это может быть «аккуратный» способ описания значения по умолчанию для свойство, и, следовательно, возможность определить, изменилось ли оно.

Вам нужно было бы использовать Reflection, чтобы идентифицировать изменения свойств - что на самом деле не , что дорого, если вы не делаете много этого!

Предупреждение: вы не сможете определить, было ли свойство изменено НАЗАД с значения, отличного от значения по умолчанию, на значение по умолчанию.

0 голосов
/ 15 сентября 2008

Я могу порекомендовать использовать Enterprise Library для этой цели. Policy Application Block обеспечивает инфраструктуру для выполнения «чего-то» (что-то = вы можете кодировать это самостоятельно), например, при каждом входе / выходе из метода. Вы можете контролировать поведение с атрибутами. Возьмем это как подсказку и подробно рассмотрим документацию корпоративной библиотеки.

0 голосов
/ 15 сентября 2008

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

Проблема такого подхода в том, что ваш прокси будет вызываться только при внешнем вызове. Я приведу вам пример.

class A
{
    [Foo]
    public int Property1{get; set;}
    public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}

Когда property1 вызывается из другого класса, ваш прокси будет вызываться. Но если другой класс вызывает property2, даже если набор property2 вызовет property1, прокси не будет вызван (прокси не нужен, когда вы находитесь в самом классе).

Существует много примеров кода использования ContextBoundObjects, посмотрите на него.

0 голосов
/ 15 сентября 2008

Другой альтернативой может быть генератор кода, такой как codemith, для автоматизации создания свойств. Это было бы особенно полезно, если создаваемые вами свойства являются столбцами в таблице базы данных

...