订阅自己的INotifyPropertyChanged

时间:2011-04-13 02:14:04

标签: c# .net inotifypropertychanged

我有一个实现INotifyPropertyChanged的类。我正在使用Simon Cropp的优秀NotifyPropertyWeaver将INotifyPropertyChanged代码注入属性中。但是我现在需要修改一堆属性的setter,以便在set完成后对所有属性做同样的事情。修改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()
    {
        ....
    }
}

3 个答案:

答案 0 :(得分:1)

首先,您只需实现OnPropertyChanged,而不必使用该事件。

其次,这被认为是不好的形式。 NotifyPropertyWeaver会对代码进行大量检查,并检测属性之间的依赖关系。例如,如果在属性B的代码中使用属性A,NotifyPropertyWeaver将在A的代码中为B添加第二个OnPropertyChanged,以确保所有内容都已更新。

简而言之,不要这样做,输入所有内容。

答案 1 :(得分:0)

我已经完成了这个/使用过的代码,并且已经注意到没有很好的副作用代码。根据您可以看到性能影响的属性数量,但它可能会很小。我注意到的是,在查看代码时,为什么在使用此模式时会发生效果并不总是立即清楚。您需要注意的是如何设计课程。当你快速整理课程时,自动属性很好,但它们可能成为你所有设计的障碍。我通常不使用它们,除非它快速模拟一个对象或它是一个非常简单的对象,我用它来传输数据。您必须问自己的问题是,您是否以这种方式设计对象,因为它最适合您的代码,程序,样式,或者因为您尝试使用特定功能,即自动属性。

要考虑的一件事是,你是否会为每个领域做同样的动作,或者你会采取不同的行动?如果你有不同的行动,你很快就会得到一个笨重的方法。如果它们是相同的操作,则可能更容易管理。

我实现INotifyProperty接口的正常方法是创建一个方法来更改字段,执行通知,并且还可以在更改后执行Action。这避免了拥有所有大条件语句并对动作进行细粒度控制,但具有足够的细粒度控制以完全灵活。如果我正在创建大量相关的对象,我通常只是创建一个基类来继承所有这些对象,将此更改方法作为受保护的方法,因此我不必每次重新实现一次。类。

答案 2 :(得分:0)

我在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的集合中。