繁体   English   中英

INotifyPropertyChanged 和反序列化

[英]INotifyPropertyChanged and Deserialization

鉴于:

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

是的,您可以通过在您的类中实现OnDeserializingOnDeserialized 序列化回调方法来做您想做的事情。 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM