事件处理-C#克隆事件处理程序

本文关键字:事件处理 程序 -C# | 更新日期: 2023-09-27 17:58:43

我有一个包含多个EventHandlers的类(除其他外):

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

我希望能够在GameObject中添加一个Clone()函数,它返回被调用对象的精确副本

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

但是,它似乎使clone.BeginStep指向与this.BeginStep相同的对象,而不是进行复制。那么,如何制作EventHandler对象的副本呢?

事件处理-C#克隆事件处理程序

您不需要担心这一点。EventHandler<EventArgs>对象是不可变的,因此任何对象中侦听器列表的任何更改都将导致该对象获得一个包含更新的调用列表的新EventHandler<EventArgs>实例。此更改将不会出现在其他GameObject中。

尝试使用+=运算符添加它。我甚至不知道可以分配一个活动。

clone.Initialize += this.Initialize;

此外,所有委托都是不可变的值类型,因此您不必担心它们指向同一个对象——当您执行如上所述的操作时,整个委托都会被复制(如果愿意的话,会被克隆)。

这取决于您的事件是委托给GameObject类中定义的方法,还是委托给其他观察者类实例。

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

    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;
    }

如果事件在不同的类中处理,则无需执行任何操作,但原始实例和克隆实例的所有事件通知都将具有相同的处理程序。如果这不是您想要的,那么您需要在克隆后更改事件代理。

您不需要克隆事件,就像不需要克隆源对象的任何方法一样。克隆时,真正需要复制的只是成员/属性值。

您将想要做一些类似于发布在深度克隆对象上的事情

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);
    }
}

您的类需要是可序列化的。

编辑:正如我所说,这是基于我链接的代码,我赶紧给出答案。应该仔细检查一下。