Какая магия компилятора нам нужна больше? - PullRequest
3 голосов
/ 01 декабря 2010

Я разрабатываю модели вида лота, которые:

1) Все должны реализовать INotifyPropertyChanged для привязки к пользовательскому интерфейсу.

2) Установщики свойств должны вызывать PropertyChanged при изменении.

3) Событие PropertyChanged должно предоставлять правильное имя свойства.

Если вы (как и я) связаны с написанием чего-либонапример:


public string Name 
{
  get 
  { 
    return _name; 
  }
  set 
  { 
    if (_name != value) 
    {
      _name = value;
      RaisePropertyChanged("Name");
    }
  }
} 

Затем выполните рефакторинг этого метода следующим образом и иногда забудьте обновить литерал имени свойства:


string _fundName;
public string FundName 
{
  get 
  { 
    return _fundName; 
  }
  set 
  { 
    if (_fundName != value) 
    {
      _fundName = value;
      RaisePropertyChanged("Name");
    }
  }
} 

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

Тогда все, что нам нужно, это какая-то магия.

Что если мне просто нужно написать это:


[Magic] // implicit transformation
public string FundName { get; set; }

или если яУ меня много свойств:


[Magic]
public class MyViewModel
{
  public string FundName { get; set; }
  public string FundType { get; set; }

  [NoMagic] // suppress transformation
  public int InternalId { get; set; }
}

Итак, я только что разработал задачу MSBuild, чтобы выполнить эту магию после сборки (http://kindofmagic.codeplex.com).

Вопрос в том, какой вид магической постобработки вы бы хотелиподробнее?

Имеет ли смысл автоматическая реализация INotifyPropertyChanging?

Ответы [ 5 ]

4 голосов
/ 02 декабря 2010

Попробуйте это

http://code.google.com/p/notifypropertyweaver/

  • Атрибуты не требуются
  • Ссылки не требуются
  • Базовый класс не требуется

Вот моя статья в блоге об этом

http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html

Поддерживает запрашиваемые вами атрибуты

  • NotifyPropertyAttribute (уведомить о свойстве)
  • NotifyForAllAttribute (уведомление для всех свойств типа)
  • NotifyIgnoreAttribute (не уведомлять о свойстве или типе)
  • Кроме того, NotifyFor (позволяет вводить код уведомления, который указывает на другое свойство)

Хотя это опция и предназначена для тонкой настройки. Большинство инъекций делается по соглашению путем анализа существующего IL.

1 голос
/ 01 декабря 2010

Если у нас будет необычная генерация кода, думаю, я бы предпочел способ более легкой генерации DependancyProperties.Фрагмент, который я использую, безусловно, полезен, но я не фанат того, как перемешивается код, когда у вас есть изменения и принудительные обратные вызовы и параметры метаданных.Может быть, я попробую макет образца после работы.

Редактировать: Ну, вот одна концепция.Было бы намного умнее, если вы передадите анонимные методы атрибутам, но это все еще на шаг вперед.

До:

[DpDefault("The Void")]
[DpCoerce(new CoerceValueCallback(MainWindow.CoerceAddress))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress1))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress2))]
[DpOptions(FrameworkPropertyMetadataOptions.Inherits)]
public string Address {
    get { return Dp.Get<string>(); }
    set {
        if (Dp.Get<string>() != value) {
            Dp.Set(value);
            PostOffice.SendMailToTheBoss("I moved!");
        }
    }
}

После:

public string Address {
    get { return (string)GetValue(AddressProperty); }
    set {
        if ((string)GetValue(AddressProperty) != value) {
            SetValue(AddressProperty, value);
            PostOffice.SendMailToTheBoss("I moved!");
        }
    }
}

public static readonly DependencyProperty AddressProperty =
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
        new FrameworkPropertyMetadata((string)"The Void",
            FrameworkPropertyMetadataOptions.Inherits,
            new PropertyChangedCallback(MainWindow.ChangeAddress1)
                + new PropertyChangedCallback(MainWindow.ChangeAddress2),
            new CoerceValueCallback(MainWindow.CoerceAddress)));

Обычно используется только атрибут «DpDefault», но даже если он не делает код короче, он, безусловно, делает его более понятным.Вот более типичный пример:

До:

[DpDefault("The Void")]
public string Address { get; set; }

После:

public string Address {
    get { return (string)GetValue(AddressProperty); }
    set { SetValue(AddressProperty, value); }
}

public static readonly DependencyProperty AddressProperty =
    DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
        new UIPropertyMetadata((string)"The Void"));
1 голос
/ 01 декабря 2010

«Магия» - это почти всегда ужасное имя для метода, свойства или переменной на любом языке. Вы должны переименовать атрибут в нечто более описательное. Представьте, что вы просто случайный интернет-пешеход и наткнулись на кусок кода с атрибутом «Волшебство», что он говорит вам о коде? Точно ничего:)

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

0 голосов
/ 01 декабря 2010

Это уже можно сделать с помощью инструмента AOP (Aspect-Oriented Programming), такого как PostSharp : http://www.richard -banks.org / 2009/02 / аспектно-ориентированного программирования.html (с использованием v1.x) http://www.sharpcrafters.com/solutions/ui#data-binding (используется v2.0)

Я использовал PostSharp для реализации INPC в нескольких проектах, и это сработало довольно хорошо, код стал намного чище и удобнее в обслуживании (для компиляции добавляется несколько секунд)

0 голосов
/ 01 декабря 2010

Что-то, что может сделать вашу жизнь немного проще, это ... (Я взял это от Caliburn Micro).

 public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) {
            NotifyOfPropertyChange(property.GetMemberInfo().Name);
        }

Это позволяет вам сделать следующее ..

NotifyOfProperyChange (() => this.PropertyName);

Это позволит выявить любые проблемы с кодом во время разработки, а не во время выполнения.

Caliburn Micro - этопотрясающая небольшая среда, на которую стоит взглянуть, она устраняет большую часть проводки, связанной с MVVM и Silverlight / WPF!

...