和事件(特别是INotifyPropertyChanged)

时间:2011-07-14 18:03:45

标签: c# events inotifypropertychanged serializable

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

我有一个包含地址的人。两者都继承自实现INotifyPropertyChanged的BaseEntity。我想要Person类到NotifyPropertyChanged(“地址”),不仅在设置地址时,而且当地址本身发生变化时,所以我在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),现在当我对Address进行更改时(somePerson.Address.Street =“new new”)该地址的PropertyChanged的invocationCount为0,它曾经是1,因此Person不会收到通知,并且本身不会触发NotifyPropertyChanged(“Address”);

同样,如果我从Person中删除[Serializable],它可以工作,如果我将其添加回去,它就不起作用。我实际上并没有序列化任何东西,我刚刚添加了[Serializable]属性。

有什么想法吗?

4 个答案:

答案 0 :(得分:2)

您的Person / Address / BaseEntity是否被序列化/反序列化,然后表现出这种行为,或者只是导致此行为的[Serializable]属性的附加内容?

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

如果你的对象没有序列化事件,那么在反序列化时,它们似乎没有出现。他们可能正在被提高,但没有人再听了。

答案 1 :(得分:2)

我的猜测(在评论中的讨论中略有刺激)是应用程序中的某些代码是检测 [Serializable]并决定序列化对象。例如,缓存可能是候选者 - 就像任何“深度克隆”代码一样。

尝试实现ISerializable(或只添加序列化回调),并添加一个断点。如果您的断点发生命中,请加载调用堆栈窗口并向上导航堆栈以查看序列化对象的内容以及原因。

答案 2 :(得分:1)

看看是否添加:

[field:NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;

诀窍。

最初来自:How to exclude nonserializable observers from a [Serializable] INotifyPropertyChanged implementor?

答案 3 :(得分:1)

我做了一点测试,并且将类序列化与没有序列化之间没有区别。这是一些工作示例代码。

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

    }

程序输出

属性更改地址

地址变更城市

属性更改地址