Given:
public class MyClass : INotifyPropertyChanged
{
public List<string> _TestFire = new List<string>();
string _StringProp;
public string StringProp
{
get
{
return _StringProp;
}
set
{
if (_StringProp != value)
{
_StringProp = value;
RaisePropertyChanged("StringProp");
_TestFire.Add("fired " + DateTime.Now);
}
}
}
}
When you serialize and then deserialize this class, it fires the RaisePropertyChanged
event, which is undesirable. Is it possible to prevent this event from being fired when the class gets deserialized?
var MyclassInstance = new MyClass() { StringProp = "None" };
MyclassInstance._TestFire.Clear(); // Clear property change history
var serobj = JsonConvert.SerializeObject();
var newitem = JsonConvert.DeserializeObject<MyClass>(serobj);
// newitem._TestFire.Count == 1, the set method was executed
Is there a way to get a bool
value if the class is being deserialized? So then I could do:
set
{
if (_StringProp != value)
{
_StringProp = value;
if (!Deserializing)
{
RaisePropertyChanged("StringProp");
_TestFire.Add("fired " + DateTime.Now);
}
}
}
Yes, you can do what you want by implementing the OnDeserializing
and OnDeserialized
serialization callback methods in your class. In the OnDeserializing
method, set your private _isDeserializing
variable to true, and in OnDeserialized
set it back to false. I would recommend doing the _isDeserializing
check inside the RaisePropertyChanged
method so you don't have duplicate code inside every property.
So you would end up with something like this:
public class MyClass : INotifyPropertyChanged
{
public List<string> _TestFire = new List<string>();
string _StringProp;
public string StringProp
{
get
{
return _StringProp;
}
set
{
if (_StringProp != value)
{
_StringProp = value;
RaisePropertyChanged("StringProp");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
// don't raise the event if the property is being changed due to deserialization
if (_isDeserializing) return;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
_TestFire.Add(propertyName + " was fired " + DateTime.Now);
}
bool _isDeserializing = false;
[OnDeserializing]
internal void OnDeserializingMethod(StreamingContext context)
{
_isDeserializing = true;
}
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context)
{
_isDeserializing = false;
}
}
Working demo: https://dotnetfiddle.net/QkOcF4
Another way you could solve this problem is to mark your public properties with [JsonIgnore]
and then mark the corresponding backing fields with [JsonProperty]
, specifying the property name to use in the JSON. This would allow Json.Net to set the backing fields directly and not execute any of the mutator logic.
public class MyClass : INotifyPropertyChanged
{
public List<string> _TestFire = new List<string>();
[JsonProperty("StringProp")]
string _StringProp;
[JsonIgnore]
public string StringProp
{
get
{
return _StringProp;
}
set
{
if (_StringProp != value)
{
_StringProp = value;
RaisePropertyChanged("StringProp");
_TestFire.Add("StringProp was fired " + DateTime.Now);
}
}
}
...
}
Working demo: https://dotnetfiddle.net/jc7wDu
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.