【问题标题】:INotifyPropertyChanged and DeserializationINotifyPropertyChanged 和反序列化
【发布时间】:2019-04-11 22:07:11
【问题描述】:

给定:

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);
            }
        }
    }
}

当您对此类进行序列化然后反序列化时,它会触发 RaisePropertyChanged 事件,这是不可取的。当类被反序列化时,是否可以防止触发此事件?

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

如果类被反序列化,有没有办法获得bool 值? 那么我可以这样做:

        set
        {
            if (_StringProp != value)
            {
                _StringProp = value;

                if (!Deserializing)
                {
                    RaisePropertyChanged("StringProp");
                    _TestFire.Add("fired " + DateTime.Now);
                }
            }
        }

【问题讨论】:

    标签: c# json.net deserialization inotifypropertychanged


    【解决方案1】:

    是的,您可以通过在课堂上实现OnDeserializingOnDeserialized serialization callback methods 来做您想做的事。在OnDeserializing 方法中,将您的私有_isDeserializing 变量设置为true,并在OnDeserialized 中将其设置回false。我建议在 RaisePropertyChanged 方法中执行 _isDeserializing 检查,这样您就不会在每个属性中都有重复的代码。

    所以你最终会得到这样的结果:

    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;
        }
    }
    

    工作演示:https://dotnetfiddle.net/QkOcF4


    解决此问题的另一种方法是用[JsonIgnore] 标记公共属性,然后用[JsonProperty] 标记相应的支持字段,指定要在JSON 中使用的属性名称。这将允许 Json.Net 直接设置支持字段,而不执行任何 mutator 逻辑。

    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);
                }
            }
        }
    
        ...
    }
    

    工作演示:https://dotnetfiddle.net/jc7wDu

    【讨论】:

    • 这非常有帮助。谢谢!
    • 同意,不敢相信我已经使用 JSON 这么长时间了,却没有遇到这个问题。 @BrianRogers 谢谢
    • 我喜欢将 JsonProperty 属性放在支持字段上的想法,这太棒了。只是为了仔细检查,因为这个问题是关于反序列化的。在序列化上也可以使用这个技巧吗?
    • @JawadSabir 是的,它应该可以工作。试一试。
    猜你喜欢
    • 2012-03-17
    • 2013-04-19
    • 2018-12-05
    • 2013-01-08
    • 2015-03-17
    • 2015-08-28
    相关资源
    最近更新 更多