What is the correct way to code event handlers for serializable model objects?

1k Views Asked by At

I'm struggling to decide the "correct" way to handle model-level events in the MVP pattern when serializing/deserializing.

For example, suppose I had a PropertyChanged event handler in my serializable base model class :

[Serializable]
public abstract class MyBaseModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

Child classes may or may not use event handler

[Serializable]
public class MyModel
{
    public MyModel()
    {
        PropertyChanged += MyModel_PropertyChanged;
    }
}

And non-serializable Presenters/ViewModels may also use this event handler

public class MyPresenter
{
    public MyPresenter(MyModel m)
    {
        m.PropertyChanged += MyPresenter_PropertyChanged;
    }
}

My problem is when I try to Clone the model object using serialization, I get an exception because MyPresenter is not marked as serializable.

This could be easily fixed by adding the [NonSerialized] attribute to the PropertyChanged event, however then when objects get deserialized they are missing the MyModel_PropertyChanged handler as well, which is only added in the constructor.

I was considering using an [OnDeserialized] method in the model, and attaching the model-level event handlers there as well, however the code base I am working with is extremely large and it would be a lot of work to go through every one of or model libraries and add the custom [OnDeserialized] method to each one, so I wanted to check if there was an alternative solution first.

Is there a way of specifying which event handlers are not serialized? Or a better of solution to this problem of how to handle event handlers in serializable objects which can be used by both the object itself and non-serializable objects?

1

There are 1 best solutions below

0
On

hmmm.. just a quick answer basically there's some logic attaching this event so you should objectify this logic

e.g. (pseudo code)

class MyHandlingLogic : IDisposable
 Target { get; set; }
 RegistrationDelegate { get; set; }
 OnTargetSet(target) { 
   this.RegistrationDelegate = ...; // some code utilizing all properties set
   target.TargetEvent += this.RegistrationDelegate; 
 }
 Dispose() { target.TargetEvent -= this.RegistrationDelegate; }
}

you can either have this logic as an object and host it in the one who is registering this (page, or controller state etc..) so in this way you serialize the parts (references) of the things that are needed for the logic to be resumed..