Автоматически INotifyPropertyChanged - PullRequest
57 голосов
/ 09 февраля 2009

Есть ли способ автоматически получать уведомления об изменениях свойств в классе без необходимости писать OnPropertyChanged в каждом сеттере? (У меня есть сотни свойств, которые я хочу знать, изменились ли они).


Антон предлагает динамические прокси . Я фактически использовал библиотеку «Castle» для чего-то похожего в прошлом, и хотя это действительно уменьшает объем кода, который я должен был написать, он прибавил около 30 секунд ко времени запуска моей программы (ymmv) - потому что это решение во время выполнения.

Мне интересно, есть ли решение времени компиляции, возможно, с использованием атрибутов времени компиляции ...


Slashene и TcKs дают предложения, которые генерируют повторяющийся код - к сожалению, не все мои свойства являются простым случаем m_Value = value - многие из них имеют собственный код в установщиках, поэтому код cookie-cutter из фрагментов и xml не действительно выполнимо для моего проекта.

Ответы [ 13 ]

1 голос
/ 07 мая 2013

Просто чтобы сделать реализацию быстрее , вы можете использовать фрагмент

С http://aaron -hoffman.blogspot.it / 2010/09 / visual-studio-code-snippet-for-notify.html

классы проектов ViewModel, следующие шаблону M-V-VM, часто необходимо вызывать событие «PropertyChanged» (для помощи в реализации интерфейса INotifyPropertyChanged) из установщика свойства. Это утомительная задача, которая, надеюсь, когда-нибудь будет решена с помощью компилятора в качестве службы ...

Ядро фрагмента (для которого полный кредит отправляется автору, а не мне):

  <Code Language= "csharp "> 
    <![CDATA[public $type$ $property$ 
{ 
    get { return _$property$; } 
    set 
    { 
        if (_$property$ != value) 
        { 
            _$property$ = value; 
            OnPropertyChanged($property$PropertyName); 
        } 
    } 
} 
private $type$ _$property$; 
public const string $property$PropertyName = "$property$";$end$]]> 
</Code> 
1 голос
/ 27 мая 2011

Улучшение для вызова мероприятия в детских классах:

Вызывается благодаря: this.NotifyPropertyChange (() => PageIndex);

Добавьте это в класс NotificationExtensions:

    /// <summary>
    /// <para>Lève l'évènement de changement de valeur sur l'objet <paramref name="sender"/>
    /// pour la propriété utilisée dans la lambda <paramref name="property"/>.</para>
    /// </summary>
    /// <param name="sender">L'objet portant la propriété et l'évènement.</param>
    /// <param name="property">Une expression lambda utilisant la propriété subissant la modification.</param>
    public static void NotifyPropertyChange(this INotifyPropertyChanged sender, Expression<Func<Object>> property)
    {
        if (sender == null)
            return;

        // Récupère le nom de la propriété utilisée dans la lambda en argument
        LambdaExpression lambda = property as LambdaExpression;
        MemberExpression memberExpression;
        if (lambda.Body is UnaryExpression)
        {
            UnaryExpression unaryExpression = lambda.Body as UnaryExpression;
            memberExpression = unaryExpression.Operand as MemberExpression;
        }
        else
        {
            memberExpression = lambda.Body as MemberExpression;
        }
        ConstantExpression constantExpression = memberExpression.Expression as ConstantExpression;
        PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;


        // il faut remonter la hierarchie, car meme public, un event n est pas visible dans les enfants
        FieldInfo eventField;
        Type baseType = sender.GetType();
        do
        {
            eventField = baseType.GetField(INotifyPropertyChangedEventFieldName, BindingFlags.Instance | BindingFlags.NonPublic);
            baseType = baseType.BaseType;
        } while (eventField == null);

        // on a trouvé l'event, on peut invoquer tt les delegates liés
        MulticastDelegate eventDelegate = eventField.GetValue(sender) as MulticastDelegate;
        if (eventDelegate == null) return; // l'event n'est bindé à aucun delegate
        foreach (Delegate handler in eventDelegate.GetInvocationList())
        {
            handler.Method.Invoke(handler.Target, new Object[] { sender, new PropertyChangedEventArgs(propertyInfo.Name) });
        }
    }
0 голосов
/ 23 января 2013

Просто используйте этот атрибут над вашей автоматической декларацией свойства

[NotifyParentProperty(true)]
public object YourProperty { get; set; }
...