和事件(特别是INotifyPropertyChanged)

本文关键字:INotifyPropertyChanged 特别是 事件 | 更新日期: 2023-09-27 18:02:20

我遇到了一个非常奇怪的问题,我不能似乎用一个小例子重现。对不起,如果这个问题有点模糊。

我有一个Person,其中包含一个Address。两者都继承了实现INotifyPropertyChanged的BaseEntity。我希望Person类通知propertychanged("地址"),不仅当地址设置时,而且当地址本身改变时,所以我在Person中的get/set看起来像这样:

class Person : BaseEntity
{
    private Address address;
    public Address Address
    {
        get { return address; }
        set
        {
            address = value;
            NotifyPropertyChanged("Address");
            // propagate changes in Address to changes in Person
            address.PropertyChanged += (s, e) => { NotifyPropertyChanged("Address"); };
        }
    }
    ...
}

这几个月来工作得很好。

我已经添加了[Serializable]到Person, Address,和BaseEntity(和[field: NonSerialized]到BaseEntity的PropertyChanged),现在当我改变地址(somePerson.Address。Street = "something new"),地址的PropertyChanged的invocationCount是0,它曾经是1,所以Person不会得到通知,也不会自己触发NotifyPropertyChanged(" address ");

再次,如果我从Person中删除[Serializable],它工作,如果我添加它,它不工作。我实际上还没有序列化任何东西,我只是添加了[Serializable]属性。

任何想法?

和事件(特别是INotifyPropertyChanged)

我的猜测(稍微受到评论讨论的启发)是,应用程序中的某些代码检测到 [Serializable]并决定序列化该对象。例如,缓存将是一个可能的候选——任何"深度克隆"代码也可能。

尝试实现ISerializable(或者只是添加一个序列化回调),并添加一个断点。如果遇到断点,则加载调用堆栈窗口并返回堆栈以查看是什么在序列化您的对象,以及为什么。

您的Person/Address/BaseEntity是否被序列化/反序列化并且然后显示此行为,或者仅仅是附加的[Serializable]属性导致此行为?

我问对象是否被反序列化,然后显示行为,因为在我的INotifyPropertyChanged的大多数实现中,我显式地将PropertyChanged事件标记为非序列化,然后在适当的反序列化时手动重新挂钩事件。(序列化事件会扩展对象图,并可能导致意外对象的序列化。)

如果您的对象没有序列化事件,那么在反序列化时,它们看起来没有触发是有意义的。他们可能被提高了,但没人再听了。

查看是否添加:

[field:NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;

可以。

原来自:如何从[Serializable] INotifyPropertyChanged实现者中排除非序列化的观察者?

我做了一点测试,类是否可序列化没有区别。下面是一些可用的示例代码。

    [Serializable]
    public class BaseEntity : INotifyPropertyChanged
    {
        [NonSerialized]
        private PropertyChangedEventHandler _propertyChanged;
        public event PropertyChangedEventHandler PropertyChanged
        {
            add { _propertyChanged += value; }
            remove { _propertyChanged -= value; }
        }
        protected void NotifyPropertyChanged(string propertyName)
        {
            _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    [Serializable]
    public class Person : BaseEntity
    {
        private Address _address;
        public Address Address
        {
            get { return _address; }
            set
            {
                _address = value;
                NotifyPropertyChanged("Address");
                Address.PropertyChanged += (s, e) =>
                                               {
                                                   Console.WriteLine("Address Property Changed {0}", e.PropertyName);
                                                   NotifyPropertyChanged("Address");
                                               };
            }
        }
    }
    [Serializable]
    public class Address : BaseEntity
    {
        private string _city;
        public string City
        {
            get { return _city; }
            set
            {
                _city = value;
                NotifyPropertyChanged("City");
            }
        }
    }
    static void Main(string[] args)
    {

        var person = new Person();
        person.PropertyChanged += (s, e) => Console.WriteLine("Property Changed {0}", e.PropertyName);
        person.Address = new Address();
        person.Address.City = "TestCity";
    }

程序输出

属性更改地址

地址变更城市

属性更改地址