简体   繁体   English

C# 克隆 EventHandler

[英]C# clone EventHandler

I have a class with multiple EventHandlers (among other things):我有一个带有多个事件处理程序(除其他外)的 class:

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.我希望能够将Clone() function 添加到 GameObject,它返回调用它的 object 的完全相同的副本。 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.但是,它似乎正在使clone.BeginStep指向与 this.BeginStep 相同的this.BeginStep而不是复制。 So, how do I make a copy of an EventHandler object?那么,如何复制 EventHandler object?

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. EventHandler<EventArgs> object 是不可变的,因此 object 中的侦听器列表中的任何更改都将导致 object 获取更新后的新调用列表EventHandler<EventArgs>实例。 This change will not be present in the other GameObject .此更改不会出现在其他GameObject

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).此外,所有委托都是不可变的值类型,因此您不必担心它们指向相同的 object - 当您执行上述操作时,整个委托将被复制(如果您愿意,则克隆)。

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.这取决于您的事件是委托给 GameObject class 中定义的方法,还是委托给其他观察者 class 实例。

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.如果事件在 GameObject class 中定义的方法中处理,并且您希望克隆中的事件由克隆实例中的方法处理,则可以使用反射从原始事件处理程序中获取方法信息,使用创建新委托克隆的实例和方法名称,然后将新委托分配为克隆的事件处理程序。

    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.如果事件在不同的 class 中处理,则无需执行任何操作,但原始实例和克隆实例的所有事件通知都将具有相同的处理程序。 If that's not what you want then you'll need to change the event delegates after you clone.如果这不是您想要的,那么您需要在克隆后更改事件代表。

You don't need to clone the events, just like you don't need to clone any methods of the source object.您不需要克隆事件,就像您不需要克隆源 object 的任何方法一样。 When you clone, all you really need to duplicate are the member/property values.克隆时,您真正需要复制的只是成员/属性值。

You'll want to do something akin to what was posted on Deep cloning objects你会想做一些类似于发布在Deep cloning objects上的事情

public static GameObject Clone(GameObject source)
{
    // Don't serialize a null object, simply return the default for that object
    if (Object.ReferenceEquals(source, null))
    {
        return default(GameObject);
    }

    IFormatter formatter = new BinaryFormatter();
    Stream stream = new MemoryStream();
    using (stream)
    {
        formatter.Serialize(stream, source);
        stream.Seek(0, SeekOrigin.Begin);
        return (GameObject)formatter.Deserialize(stream);
    }
}

Your class will need to be serializable.您的 class 需要可序列化。

EDIT: As I said, it was based off of the code I linked to, and I hurried to give the answer.编辑:正如我所说,它基于我链接到的代码,我赶紧给出答案。 Should've checked it a little closer.应该再仔细检查一下。

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

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