2011-06-09 107 views
4

我有多个事件处理类(除其他事项外):C#克隆事件处理

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

我希望能够加入一个Clone()功能游戏物体,它返回对象完全相同的副本,它被称为上。我试图做这样的:

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

但是,看来,它正在clone.BeginStep指向同一个对象this.BeginStep,而不是制作副本。那么,我如何制作一个EventHandler对象的副本?

+0

这对你有帮助吗? http://stackoverflow.com/questions/78536/cloning-objects-in-c – Akhil 2011-06-09 16:45:19

回答

6

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

0

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

3

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

clone.Initialize += this.Initialize; 

此外,所有代表都是不可变的值类型,所以你不必担心它们指向同一个对象 - 当你像上面的操作,整个委托复制(克隆,如果你愿意)。

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

你的类发布将需要序列化。

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

+0

克隆?这在技术上是有效的,但这很具误导性。要么通用,并将其称为Clone ,或者不要使其通用,并删除通用参数。 – ShdNx 2011-06-09 17:19:45

1

它取决于您的事件是否委托给GameObject类中定义的方法,或者它们是否委托给某个其他观察者类实例。

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

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

如果事件在不同的类来处理,那么你不需要做任何事,但针对原始实例和克隆实例willhave相同处理的所有事件通知。如果这不是你想要的,那么你需要在克隆之后更改事件委托。