简体   繁体   English

如何手动将非序列化的INotifyPropertyChanged事件处理程序重新挂钩到反序列化的对象

[英]How to manually re-hook a non-serialized INotifyPropertyChanged event handler to the deserialized object

Any event handlers marked as [NonSerialized] get destroyed on deserialization, so you need to manually re-hook all the required event handlers to the deserialized object after deserialization [Binary]. 在反序列化过程中,任何标记为[NonSerialized]的事件处理程序都会被销毁,因此您需要在反序列化[Binary]之后手动将所有必需的事件处理程序重新挂钩到反序列化的对象。 The only problem is, I don't know how to do that. 唯一的问题是,我不知道该怎么做。 Any help? 有什么帮助吗?

My serializable class: 我的可序列化类:

[Serializable]
public class DownloadEntry : INotifyPropertyChanged
{
    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public string DownloadID { get; set; }
    public Uri DownloadLink { get; set; }
    public string FileName { get; set; }
    private long size;
    public long Size
    {
        get { return size; }
        set
        {
            size = value;
            OnPropertyChanged("Size");
        }
    }
    public string SizePretty
    {
        get
        {
            return Helper.SizeSuffix(Size);
        }
        set
        {
            SizePretty = Size.ToString();
        }
    }
    private string timeleft;
    public string TimeLeft
    {
        get { return timeleft; }
        set
        {
            timeleft = value;
            OnPropertyChanged("TimeLeft");
        }
    }
    private string status;
    public string Status
    {
        get { return status; }
        set
        {
            status = value;
            OnPropertyChanged("Status");
        }
    }
    private string transferrate;
    public string TransferRate
    {
        get { return transferrate; }
        set
        {
            transferrate = value;
            OnPropertyChanged("TranferRate");
        }
    }
    public DateTime DateAdded { get; set; }
    public DateTime LastTryDate { get; set; }
    public string SaveTo { get; set; }
    public string Q { get; set; }
    public string Description { get; set; }
    public string AuthUsername { get; set; }
    public string AuthPassword { get; set; }
    public string ObtainedFrom { get; set; }
    [NonSerialized]
    private bool running;
    public bool Running 
    { 
        get { return running; } 
        set 
        { 
            running = value;
            OnPropertyChanged("Running");
        }
    }
}

Class where serialization and deserialization takes place: 进行序列化和反序列化的类:

public static class Downloads
{
    public static ObservableCollection<DownloadEntry> DownloadEntries = new ObservableCollection<DownloadEntry>();

    public static void Deserialize()
    {
        if (File.Exists("downloads.dat"))
        {
            IFormatter formatter = new BinaryFormatter();
            using (FileStream stream = File.OpenRead("downloads.dat"))
            {
                DownloadEntries = (ObservableCollection<DownloadEntry>)formatter.Deserialize(stream);
            }
        }
    }

    public static void Serialize()
    {
        IFormatter formatter = new BinaryFormatter();
        using (FileStream stream = File.Create("downloads.dat"))
        {
            formatter.Serialize(stream, DownloadEntries);
        }
    }
}

What I found on here, but there were no explanations on how to do it. 我在这里找到了什么,但是没有关于如何执行的解释。

https://stackoverflow.com/a/6697942/4932305 : https://stackoverflow.com/a/6697942/4932305

most of my implementations of INotifyPropertyChanged I explicitly mark the PropertyChanged event as being non-serialized and then manually re-hook the event upon deserialization as appropriate. 我的INotifyPropertyChanged的大多数实现都将PropertyChanged事件明确标记为未序列化,然后在反序列化后适当地手动重新挂钩该事件。

Code present but it's in VB.net: Events not working with after Deserialization : 代码存在,但在VB.net中: 反序列化后事件无法使用

The problem is not that the Changed event isn't being fired; 问题不在于未触发Changed事件。 as long as the same class definition (with the setter that raises the event) is used for the deserialized object (with DataContract serialization that isn't a requisite), the event will be raised. 只要将相同的类定义(带有引发事件的setter)用于反序列化的对象(不需要使用DataContract序列化),就会引发该事件。 What's happening is that the deserialized object no longer has the handler attached. 发生的事情是,反序列化的对象不再具有附加的处理程序。

You cannot serialize or deserialize event handlers; 您不能序列化或反序列化事件处理程序; at the very least, you shouldn't. 至少,您不应该这样做。 Because they may point to references other than the current object reference, and because the deserialized object is a new reference in what is probably a different runtime, event handler references from the serialized object are useless on deserialization, because the reference will no longer point to the expected object in the new runtime's heap. 因为它们可能指向当前对象引用以外的引用,并且由于反序列化的对象是新的引用(可能与运行时不同),所以序列化对象的事件处理程序引用在反序列化时无用,因为该引用将不再指向新运行时堆中的预期对象。

You have to implement your static class to Deserialized it using the serialized contents (xml or binary) and subscribe to required events. 您必须使用序列化的内容(xml或二进制)来实现静态类以对其进行反序列化,并订阅所需的事件。

public static DownloadEntry Deserialize(string serializedXmlContents) 
{
    DownloadEntry downloadEntry= ... // Do the deserialization
    // Subscribe to your events
    return downloadEntry;
}

The solution is here: http://web.archive.org/web/20150531190503/http://www.gavaghan.org/blog/2007/07/20/demonstrating-bindinglist-serialization-bug/ 解决方案在这里: http : //web.archive.org/web/20150531190503/http : //www.gavaghan.org/blog/2007/07/20/demonstrating-bindinglist-serialization-bug/

Because I couldn't apply it to my ObservableCollection. 因为我无法将其应用于我的ObservableCollection。 I just used a BindingList, which acts pretty much the same as an ObservableCollection. 我只是使用了BindingList,其作用与ObservableCollection几乎相同。 All I had to do was change CollectionChanged event to ListChanged and my problem was solved. 我要做的就是将CollectionChanged事件更改为ListChanged,问题解决了。

I have spent days obsessing over this. 我已经花了几天时间沉迷于此。 Thankfully, that's over now. 幸运的是,现在结束了。

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

相关问题 访问C#中非序列化类中包含的序列化对象 - Accessing a serialized object contained in non-serialized class in c# 在非序列化方法上对不可序列化对象进行XML序列化时出错 - Error on XML serializing on a non-serializable object on a non-serialized method 在不进行序列化/反序列化(C#)的情况下将“非序列化”对象传递到另一个应用程序域 - Pass a “non-serialized” object to another appdomain without Serilization/Deserialization (C#) 在 C# 中默认使字段非序列化 - make fields non-serialized by default in c# INotifyPropertyChanged事件未调用事件处理程序 - INotifyPropertyChanged Event Not Calling Event Handler INotifyPropertyChanged事件处理程序始终为null - INotifyPropertyChanged Event handler is always null 原始序列化对象以外的反序列化对象 - Deserialized object other than original serialized object 如何在WinRT中将异步事件处理程序连接到非异步事件? - How can I hook up an async event handler to a non async event in WinRT? 通过 webservices c# 发送非序列化对象的最简单方法 - Easiest way to send non-serialized objects through webservices c# 如何避免手动实现INotifyPropertyChanged - How to avoid implementing INotifyPropertyChanged manually
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM