Thursday, January 06, 2005
« Limitation on manual declaration of C# e... | Main | Less choice leads to better results? »

OK, I figured it out (I think)

 

    [NonSerialized]

    EventHandler _nonSerializableHandlers;

    EventHandler _serializableHandlers;

 

    /// <summary>

    /// Declares a serialization-safe IsDirtyChanged event.

    /// </summary>

    public event EventHandler IsDirtyChanged

    {

      add

      {

        if (value.Target.GetType().IsSerializable)

          _serializableHandlers =

             (EventHandler)Delegate.Combine(_serializableHandlers, value);

        else

          _nonSerializableHandlers =

             (EventHandler)Delegate.Combine(_nonSerializableHandlers, value);

      }

      remove

      {

        if (value.Target.GetType().IsSerializable)

          _serializableHandlers =

            (EventHandler)Delegate.Remove(_serializableHandlers, value);

        else

          _nonSerializableHandlers =

            (EventHandler)Delegate.Remove(_nonSerializableHandlers, value);

      }

    }

 

    /// <summary>

    /// Call this method to raise the IsDirtyChanged event.

    /// </summary>

    virtual protected void OnIsDirtyChanged()

    {

      if (_nonSerializableHandlers != null)

        _nonSerializableHandlers(this, EventArgs.Empty);

      if (_serializableHandlers != null)

        _serializableHandlers(this, EventArgs.Empty);

    }

 

I temporarily forgot that C# makes you invoke the delegate directly anyway, so having a separate clause in the manual event declaration isn’t required. I still think it makes the code easier to read, but functionality is king in the end.


Saturday, January 08, 2005 7:17:18 PM (Central Standard Time, UTC-06:00)
In C# you can also put a [field:NonSerialized] attribute on the event declaration. wouldn't that solve your problem too? (i.e never serialize the event's invocation list)

Roy.
Saturday, January 08, 2005 11:57:04 PM (Central Standard Time, UTC-06:00)
Yes, that's what I did in my Business Objects books for the CSLA .NET framework.

However, that approach "feels" like a hack. You are really telling the compiler to do some magic with that approach and I never liked it (even though I obviously used it).

This approach is much more explicit and allows you to accomplish the same thing as the field: target on the attribute, or do what I show here, which preserves those event listeners that would be appropriate.

I suspect that a custom attribute that could be applied on the event listener to opt out of being serialized (even if the class is otherwise serializable) would be a nice touch here as well, and is probably something I'll put into CSLA .NET 2.0.
Thursday, August 25, 2005 8:17:21 PM (Central Standard Time, UTC-06:00)
Couldn't you also serialize static delegates in addition to non-static ones in serializable classes? For example:

public event EventHandler IsDirtyChanged
{
add
{
if (value.Method.IsStatic || value.Target.GetType().IsSerializable)
_serializableHandlers += value;
else
_nonSerializableHandlers += value;
}
remove
{
if (value.Method.IsStatic || value.Target.GetType().IsSerializable)
_serializableHandlers -= value;
else
_nonSerializableHandlers -= value;
}
}
Will
Comments are closed.