INotifyPropertyChanged 订阅自我
Posted
技术标签:
【中文标题】INotifyPropertyChanged 订阅自我【英文标题】:INotifyPropertyChanged subscribing to self 【发布时间】:2011-08-04 08:40:42 【问题描述】:我有一个实现 INotifyPropertyChanged 的类。我正在使用 Simon Cropp 的出色 NotifyPropertyWeaver 将 INotifyPropertyChanged 代码注入到属性中。但是,我现在需要修改一组属性的设置器,以便在设置完成后都执行相同的操作。修改 setter 需要创建支持字段、实现 get、实现 set 等,所有这些都具有相同的实现,除了支持字段的名称。我只是通过使用NotifyPropertyWeaver 避免了所有这些。
相反,我可以让我的班级订阅它自己的 PropertyChanged 事件并在事件处理程序中处理更改后操作。这是安全的事情吗?我意识到如果我的操作修改了我正在观察的属性之一,我将不得不注意导致堆栈溢出的无限递归。还有其他需要注意的问题吗?
这是一个例子
public class Foo : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public Prop1 get; set;
public Prop2 get; set;
public Prop3 get; set;
public Prop4 get; set;
public Foo()
this.PropertyChanged +=
new PropertyChangedEventHandler(Foo_PropertyChanged);
private void Foo_PropertyChanged(object sender, PropertyChangedEventArgs e)
switch (e.PropertyName)
case "Prop1":
case "Prop2":
case "Prop3":
DoSomething();
break;
case "Prop4":
DoSomethingElse();
break;
private void DoSomething()
....
private void DoSomethingElse()
....
编辑
Joel Lucsy 好心指出我不需要订阅该活动。我一直允许 NotifyPropertyWeaver 注入 OnPropertyChanged。相反,我可以自己实现 OnPropertyChanged 来完成同样的事情。
更新代码:
public class Foo : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public Prop1 get; set;
public Prop2 get; set;
public Prop3 get; set;
public Prop4 get; set;
private void OnPropertyChanged(string propertyName)
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
switch (propertyName)
case "Prop1":
case "Prop2":
case "Prop3":
DoSomething();
break;
case "Prop4":
DoSomethingElse();
break;
private void DoSomething()
....
private void DoSomethingElse()
....
【问题讨论】:
您能否提供一个更真实的代码示例,以便我更好地了解您想要实现的目标? 【参考方案1】:一方面,您只需实现 OnPropertyChanged 而不必使用该事件。
第二,这被认为是不好的形式。 NotifyPropertyWeaver 会检查代码并检测属性之间的依赖关系。例如,如果您在属性 B 的代码中使用属性 A,NotifyPropertyWeaver 将在 A 的代码中为 B 添加第二个 OnPropertyChanged,以确保所有内容都已更新。
简而言之,不要那样做,输入所有内容。
【讨论】:
好点,如果我显式实现 OnPropertyChanged 而不是期望 NotifyPropertyWeaver 为我完成,则无需订阅该事件。 我同意 NotifyPropertyWeaver 将处理属性之间的依赖关系。然而,这不是我想要完成的。拥有 10 个类,每个类包含 5 个属性,除了支持字段名称外,它们都具有完全相同的 12 行实现,不仅乏味,而且容易出错。我希望让事情更易于阅读和维护,这就是我使用 NotifyPropertyWeaver 的原因。 您可以尝试几件事。 PostSharp 将允许您比 NotifyPropertyWeaver 更灵活。或者您可以尝试我认为称为 T4 的内置模板。或者使用sn-ps生成代码。 @Joel 您能否详细说明 PostSharp 在这种情况下如何比 NPW 更灵活?我很想知道我可能缺少哪些功能 @Simon PostSharp 可以做的很多不仅仅是INotifyPropertyChanged。一些具体场景可以在here找到。【参考方案2】:我已经完成了这个/使用了以前做过的代码,并且没有注意到代码方面有很大的副作用。根据属性的数量,您可能会看到性能下降,但它可能会很小。我注意到的是,在查看代码时,在使用此模式时为什么会发生效果并不总是很清楚。你必须注意的是你是如何设计你的课程的。当您快速组合类时,自动属性很好,但它们可能会成为您整体设计的障碍。我通常不使用它们,除非它是一个对象的快速模型,或者它是我用来传输数据的一个非常简单的对象。您必须问自己的问题是,您是否以这种方式设计对象,是因为它最适合您的代码、程序、样式,还是因为您正在尝试使用特定功能,即自动属性。
要考虑的一件事是,您是要对每个字段执行相同的操作,还是要执行不同的操作?如果你有不同的动作,你很快就会得到一个大而笨重的方法。如果它们是相同的操作,则可能更易于管理。
我实现INotifyProperty
接口的正常方式是创建一个更改字段的方法,执行通知,也可以在更改完成后带一个Action
执行。这避免了拥有所有大的条件语句并提供对动作的细粒度控制,但具有足够的细粒度控制以完全灵活。如果我要创建很多相关的对象,我通常也只是创建一个基类来继承所有这些对象,并将此更改方法作为受保护的方法,因此我不必每次重新实现一次模式类。
【讨论】:
自动属性如何成为设计的障碍?如果您需要向 getter 或 setter 添加逻辑/检查,您不会简单地创建一个支持字段并将属性扩展为显式实现吗? @Aydsman 我想说的是,如果您围绕它们进行设计以保留它们,而不是用支持字段替换它们,它们可能会成为障碍。当您不需要支持字段时,它们很棒(喜欢它们),但您不应该仅仅因为想要使用它们而避免制作支持字段。 你能告诉我关于你上面提到的行动方法的任何信息吗? @DarthChucks 该模式并非来自任何地方,而是从经验和需求中有机地发展而来。我相信有人也在某处写过它,我只是没有想到它的参考资料。如果您想要一个如何实现它的示例,我可以提供它。 我明白了。抱歉,我没有从你的帖子中明白这一点。我绝对同意;为了保留汽车属性而进行的黑客攻击是愚蠢和危险的。自动属性的美妙之处在于您可以在不破坏 API 兼容性的情况下扩展它们。【参考方案3】:我已向 NotifyPropertyWeaver 添加了 On_PropertyName_Changed 功能 http://code.google.com/p/notifypropertyweaver/wiki/On_PropertyName_Changed
所以如果你写这个
public class Foo : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public string Prop1 get; set;
public string Prop2 get; set;
public string Prop3 get; set;
public string Prop4 get; set;
void OnProp3Changed()
void OnProp4Changed()
对 OnProp3Changed 和 OnProp4Changed 的调用将分别注入到 Prop3 和 Prop4 的集合中。
【讨论】:
以上是关于INotifyPropertyChanged 订阅自我的主要内容,如果未能解决你的问题,请参考以下文章
使用属性... INotifyPropertyChanged