2011-06-09 75 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相同處理的所有事件通知。如果這不是你想要的,那麼你需要在克隆之後更改事件委託。