C#clone EventHandler

时间:2011-06-09 16:40:27

标签: c# event-handling

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

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对象的副本呢?

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

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

clone.Initialize += this.Initialize;

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

答案 2 :(得分:1)

这取决于您的事件是否委托给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;
    }

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您需要做的事情类似于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);
    }
}

您的课程需要序列化。

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