我们需要更多什么样的编译魔术?

时间:2010-12-01 16:34:45

标签: wpf silverlight aop inotifypropertychanged mono.cecil

我开发了很多视图模型:

1)所有必须实现INotifyPropertyChanged才能绑定到UI。

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");
    }
  }
} 

然后花一天时间来调试为什么你的UI没有刷新,数据绑定无法正常工作。

然后我们所需要的只是某种魔力。

如果我只需要写这个怎么办:


[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 个答案:

答案 0 :(得分:4)

试试这个

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

  • 无需属性
  • 无需参考
  • 不需要基类

这是关于它的博客文章

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

它支持您请求的属性

  • NotifyPropertyAttribute(通知属性)
  • NotifyForAllAttribute(对类型的所有属性进行通知)
  • NotifyIgnoreAttribute(不通知属性或类型)
  • AlsoNotifyFor(允许注入指向不同属性的通知代码)

虽然这些是可选项并且专为微调而设计。大多数注射是通过分析现有的IL来按惯例完成的。

答案 1 :(得分:1)

对于任何语言的方法或属性或变量,“魔术”几乎总是一个可怕的名称。您应该将属性重命名为更具描述性的内容。想象一下,你只是一个随机的互联网行人,偶然发现了一个带有“Magic”属性的片段代码,它告诉你什么代码?完全没有:)

无论如何我会尝试你的代码,它有可能相当节省时间。这绝对应该是.NET的一部分。

答案 2 :(得分:1)

如果我们要生成花哨的代码,我想我更喜欢一种更容易生成DependancyProperties的方法。我使用的snippit肯定是有帮助的,但是当你有改变和强制回调以及元数据选项时,我不是一个粉丝,代码看起来是多么混乱。也许我会在下班后试着模拟样品。

编辑:嗯,这是一个概念。如果你将匿名方法传递给属性会更聪明,但它仍然是一个进步。

在:

[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"));

答案 3 :(得分:0)

可能会让你的生活变得更轻松的事情......(我从Caliburn Micro那里拿起它)。

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

这使您可以执行以下操作..

  

NotifyOfProperyChange(()=&gt;   this.PropertyName);

这将突出显示设计时代码的任何问题,而不是运行时间。

Caliburn Micro是一个非常棒的小框架,你应该看看它,它消除了与MVVM和Silverlight / WPF有关的大量连线!

答案 4 :(得分:0)

这已经可以使用AOP(面向方面​​编程)工具完成,例如PostSharphttp://www.richard-banks.org/2009/02/aspect-oriented-programming.html(使用v1.x) http://www.sharpcrafters.com/solutions/ui#data-binding(使用v2.0)

我使用PostSharp在少数几个项目中实现INPC,效果非常好,代码更清晰,更易于维护(编译时间增加了几秒)