Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# clone EventHandler

I have a class with multiple EventHandlers (among other things):

public GameObject
{
    public event EventHandler<EventArgs> Initialize;
    public event EventHandler<EventArgs> BeginStep;
    ....
}

I want to be able to add a Clone() function to GameObject, which returns an exact duplicate of the object it was called on. I tried doing it like this:

    public GameObject Clone()
    {
        var clone = new GameObject()
        {
            Initialize = this.Initialize,
            BeginStep = this.BeginStep,
        };
    }

But, it appears that it is making clone.BeginStep point to the same object as this.BeginStep instead of making a copy. So, how do I make a copy of an EventHandler object?

like image 769
Entity Avatar asked Jun 09 '11 16:06

Entity


3 Answers

You don't need to worry about that. The EventHandler<EventArgs> object is immutable so any change in the list of listeners in either object will cause that object to get a new EventHandler<EventArgs> instance containing the updated invocation list. This change will not be present in the other GameObject.

like image 171
Fredrik Mörk Avatar answered Sep 25 '22 13:09

Fredrik Mörk


Try adding it with the += operator. I didn't even know it was possible to assign an event.

clone.Initialize += this.Initialize;

Also, all delegates are immutable value types, therefore you don't have to worry about them pointing to the same object - when you an operation like above, the whole delegate is copied (cloned, if you will).

like image 29
ShdNx Avatar answered Sep 21 '22 13:09

ShdNx


It depends on whether your events are delegating to methods defined in the GameObject class or whether they delegate to to some other observer class instance.

If the events are handled in methods defined in your GameObject class and you want events in the clone to be handled by methods in your clone instance, you can get use reflection to get the method info from the original event handlers, create a new delegate using the cloned instance and the method name, and then assign the new delegate as the cloned event handler.

    public GameObject Clone()
    {
        var clone = new GameObject();
        foreach (var target in this.Initialize.GetInvocationList())
        {
            var mi = target.Method;
            var del = Delegate.CreateDelegate(
                          typeof(EventHandler<EventArgs>), clone, mi.Name);
            clone.Initialize += (EventHandler<EventArgs>)del;
        }
        return clone;
    }

If the events are handled in a different class, then you don't need to do anything, but all event notifications for both the original instance and cloned instance willhave the same handlers. If that's not what you want then you'll need to change the event delegates after you clone.

like image 25
lee_greco Avatar answered Sep 23 '22 13:09

lee_greco