У меня есть класс с кучей свойств, которые выглядят так:
public string Name
{
get { return _name; }
set { IsDirty = true; _name = value; }
}
Было бы намного проще, если бы я мог полагаться на C# 3.0 для создания хранилища резервных копий для них, но есть ли способ исключить IsDirty = true; так что я могу написать свои свойства примерно так и по-прежнему вести себя так же:
[MakesDirty]
public string Name { get; set; }





Вы можете попробовать настроить фрагмент кода, чтобы упростить их создание.
Другой альтернативой может быть генератор кода, например производитель кодов, для автоматизации создания свойств. Это было бы особенно полезно, если свойства, которые вы создаете, являются столбцами в таблице базы данных.
Объект ContextBound. Если вы создаете класс, расширяющий объект, связанный с контекстом, и создаете ContextAttribute, вы можете перехватывать вызовы, сделанные для такого свойства, и устанавливать IsDirty. .NET создаст прокси для вашего класса, поэтому все вызовы будут проходить через приемник удаленного взаимодействия.
Проблема с таким подходом заключается в том, что ваш прокси будет вызываться только при внешнем вызове. Приведу вам пример.
class A
{
[Foo]
public int Property1{get; set;}
public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}
Когда свойство1 вызывается из другого класса, будет вызван ваш прокси. Но если другой класс вызывает свойство2, даже если набор свойств2 будет вызывать свойство1, прокси не будет вызываться (прокси не требуется, когда вы находитесь в самом классе).
Существует много примеров кода с использованием ContextBoundObjects, изучите его.
Амир, технически это решение - однако лично я не думаю, что это хорошее место для применения этого :) Хороший ответ - однако не могу проголосовать за него в контексте этого вопроса. Извините за каламбур :)
Нет. Не без написания значительно большего (загадочного?) Кода, чем в исходной версии. (Вам нужно будет использовать отражение для проверки атрибута в свойстве, а что нет… я уже упоминал, что он «медленнее») .. Это тип дублирования, с которым я могу жить.
У MS такая же потребность в возбуждение событий при изменении свойства. INotifyPropertyChanged, который является жизненно важным интерфейсом для уведомлений об изменениях. Все реализации, которые я видел делает
set
{
_name = value;
NotifyPropertyChanged("Name");
}
Если бы это было возможно, я бы подумал, что у этих умных парней из MS уже есть что-то подобное ...
Я могу порекомендовать для этого использовать Корпоративная библиотека. Блок приложения политики предоставляет инфраструктуру, чтобы делать «что-то» (что-то = вы можете кодировать это самостоятельно), например, каждый раз, когда вы входите / выходите из метода. Вы можете управлять поведением с помощью атрибутов. Воспринимайте это как намек и подробно рассмотрите документацию корпоративной библиотеки.
Существует атрибут DefaultValueAttribute, который может быть назначен свойству, он в основном используется инструментами дизайнера, чтобы они могли указать, когда свойство было изменено, но это может быть «аккуратный» способ описания значения свойства по умолчанию. , и, таким образом, возможность определить, изменилось ли оно.
Вам нужно будет использовать Reflection для идентификации изменений свойств - что на самом деле не дорого который, если вы не делаете этого много!
Предостережение: вы не сможете определить, было ли свойство изменено НАЗАД со значения, отличного от значения по умолчанию, на значение по умолчанию.
Нет, когда вы используете автоматические свойства, у вас нет никакого контроля над реализацией. Лучшим вариантом является использование инструмента для создания шаблонов, фрагментов кода или создания частного 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);
}
}
Но тогда вам придется дублировать метод SetValue <T> в каждом таком классе. Если вы превратите его в общедоступный статический / служебный метод, вам придется выставить состояние IsDirty .. Не круто :)
@Gishu: Да, вы бы продублировали вызов SetValue в каждом свойстве и, возможно, в каждом классе. В зависимости от того, как получены ваши расчеты, будет определяться, являются ли SetValue (и, следовательно, IsDirty) общедоступными.
Это не работает: connect.microsoft.com/VisualStudio/feedback/details/304501/…
Я бы сказал, что лучший способ решить эту проблему - использовать аспектно-ориентированное программирование (АОП). Матс Хеландер сделал напишите об этом в InfoQ. Статья немного запутанная, но за ней можно следить. Существует ряд различных продуктов, которые выполняют АОП в пространстве .NET, я рекомендую PostSharp.
Если вы все же используете атрибуты, я почти уверен, что вам придется использовать используй свою собственную логику, чтобы понять, что они означают и что с ними делать. Независимо от того, что использует ваши настраиваемые объекты класса, необходимо иметь способ выполнения этих действий / проверок атрибутов, предпочтительно при создании экземпляра.
В противном случае вы рассматриваете возможность использования событий. Вам все равно придется добавлять событие к каждому методу набора, но преимущество будет заключаться в том, что вы не будете жестко кодировать, что делать с грязными наборами для каждого свойства, и сможете контролировать в одном месте то, что должно быть сделано. Это, по крайней мере, привело бы к более частому повторному использованию кода.
Если вы действительно хотите пойти по этому пути, изменить то, что делает код с помощью атрибута, есть несколько способов сделать это, и все они связаны с АОП (аспектно-ориентированное программирование). Обратите внимание на PostSharp, который является послекомпилятором, который может изменять ваш код на этапе после компиляции. Например, вы можете настроить один настраиваемый атрибут для своих свойств (или аспекта, как он называется в AOP), который вводит код внутри средств установки свойств, который помечает ваши объекты как грязные. Если вам нужны примеры того, как это достигается, вы можете проверить их учебные пособия.
Но будьте осторожны с АОП, потому что с его помощью вы можете так же легко создать больше проблем, которые вы пытаетесь решить, если использовать неправильно.
Существует больше фреймворков АОП, некоторые из которых используют пост-компиляцию, а некоторые используют механизмы перехвата методов, которые присутствуют в .Net, причем последние имеют некоторые недостатки в производительности по сравнению с первым.
PostSharp идеально подходит для подобного сценария!
Похоже, это невозможно (спасибо, Гишу), поэтому я буду использовать для этого шаблоны CodeRush. Спасибо, что напомнили мне о сниппетах.