Wpf 我们还需要什么样的编译器魔法?
我开发了以下地块视图模型: 1) 所有这些都必须实现INotifyPropertyChanged才能绑定到UI 2) 属性设置器必须在更改时引发PropertyChanged 3) PropertyChanged事件必须提供正确的属性名称 如果你(像我一样)喜欢写这样的东西:Wpf 我们还需要什么样的编译器魔法?,wpf,silverlight,aop,inotifypropertychanged,mono.cecil,Wpf,Silverlight,Aop,Inotifypropertychanged,Mono.cecil,我开发了以下地块视图模型: 1) 所有这些都必须实现INotifyPropertyChanged才能绑定到UI 2) 属性设置器必须在更改时引发PropertyChanged 3) PropertyChanged事件必须提供正确的属性名称 如果你(像我一样)喜欢写这样的东西: public string Name { get { return _name; } set { if (_name != value) { _nam
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任务,以便在生成()之后完成这项工作
问题是,你更喜欢哪种神奇的后处理
INotifyPropertyChanging的自动实现有意义吗?这可能会让您的生活更轻松一点。。。(我从Caliburn Micro上捡到的)
公共虚拟void NotifyOfPropertyChange(表达式属性){
NotifyOfPropertyChange(property.GetMemberInfo().Name);
}
这使您能够执行以下操作
财产变更通知(()=>
此名称为
这将在设计时而不是运行时突出显示代码的任何问题
Caliburn Micro是一个非常棒的小框架,您应该看看它,它消除了MVVM和Silverlight/WPF所涉及的大量连接 在任何语言中,“Magic”几乎总是一个可怕的方法、属性或变量名称。您应该将属性重命名为更具描述性的名称。想象一下,你只是一个随机上网的行人,偶然发现了一段带有“Magic”属性的代码,这段代码告诉了你什么?完全没有:)
不管怎样,我都会尝试你的代码,它有相当大的节省时间的潜力。这肯定是.NET的一部分。这可以通过使用AOP(面向方面编程)工具来完成,如:(使用v1.x) (使用v2.0)
我用PostSharp在几个项目中实现了INPC,效果非常好,代码更干净,更易于维护(编译时间增加了几秒钟)如果我们要生成奇特的代码,我想我更喜欢一种更容易生成依赖性属性的方法。我使用的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!");
}
}
}
[DpDefault("The Void")]
public string Address { get; set; }
通常,只会使用“DpDefault”属性,但即使它不会使代码更短,也肯定会使代码更清晰。下面是一个更典型的例子:
之前:
[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!");
}
}
}
[DpDefault("The Void")]
public string Address { get; set; }
之后:
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)));
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"));
试试这个
- 不需要属性
- 无需参考资料
- 不需要基类
- NotifyPropertyAttribute(通知属性)
- NotifyForAllAttribute(通知类型上的所有属性)
- NotifyIgnoreAttribute(不通知属性或类型)
- AlsoNotifyFor(允许注入指向不同属性的notify代码)
尽管这些都是可选的,并且是为微调而设计的。大多数注射都是通过分析现有的IL来完成的。我也一直在使用C.M。但是,坦率地说,这只是为了获得正确的属性名称而浪费了大量CPU周期。KindOfMagic项目背后的主要原因是使其性能尽可能好,并且用户尽可能不用打字。一个月前我曾尝试过INPC的PostSharp,但为setters生成的IL代码太臃肿难看了(我使用了Reflector)。我的观点是,通用AOP工具为这个微小的特殊问题引入了太大的开销。您是否通过任何性能测试验证了这一观点?根据我的经验,AOP在这种情况下引入的开销是无法感知的。re postsharp bloat它向每个属性中注入了大约150行代码。@Robert,我只需要适当地检查新旧值,如果不同,则引发事件。我既不需要星际飞船“企业号”也不需要太空堡垒“卡拉狄加号”。@Simon,它可以在每个属性中注入10000行代码,只要用户没有注意到性能差异,就不会困扰我。不过,我并没有花太多时间(事实上,任何时间)用反射器在我的二传中四处走动,所以也许我做错了什么。或者是对的。名为魔法的属性,肯定会吸引我的注意力。但是,我同意你的看法。寻找更好的名称,有什么想法吗?这不是一个真正的答案。intsomeProperty{get;set;}[NotifyPropertyChanged]有什么问题吗?为InotifyPropertyChange创建相同的名称怎么样?@CommanderZ您实现并使用InotifyPropertyChanged吗?如果是,原因是什么?也许你想评论一下这个好主意。通过提取OnDependencyPropertyChanged处理程序中的setter,我们可以从普通属性生成依赖属性。并使用正确的派生名称(如果不存在)生成DependencyProperty静态只读字段。使用代码转换的模拟概念编辑答案。可能是因为外来项目宿主;)顺便说一句,喜欢删除引用的想法。我只是来删除属性;)@莱克斯很高兴你喜欢它。我的方法和你的计划相似吗?你还能想到更多的功能吗?@Lex我也支持你拥有自己的属性。请参阅“在项目文件中没有引用”