和事件(特别是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]属性。
任何想法?
我的猜测(稍微受到评论讨论的启发)是,应用程序中的某些代码检测到 [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";
}
程序输出
属性更改地址
地址变更城市
属性更改地址