Answer the question
In order to leave comments, you need to log in
Object.MemberwiseClone() method and event handlers?
Good afternoon, I'm new to programming, so I apologize in advance for a possibly stupid question. Recently I encountered such a problem, there is an object of some class which causes some event. There is also another object containing the first object as one of its variables. Both the first and the second object implemented the ICloneable interface, which used the Object.MemberwiseClone() method to copy a set of value properties. So: when an event occurs in a clone object, the handler method was called on the first original object, and not on the clone object (as expected). I did not find a solution to this problem, I had to abandon the Object.MemberwiseClone() method and manually reassign the values of all variables to the new clone object. The question is: if someone has come across a similar problem, maybe he knows the solution, how to make event handlers copied instead of referring to the original object?? Here is an example with a similar situation:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Событие_и_клонирование
{
class Program
{
// Объявить тип делегата для события.
delegate void MyEventHandler();
// Объявить класс, содержащий событие.
class MyEvent: ICloneable
{
public int number { get; set; } //Номер объекта
public string name { get; set; } //Имя объекта
public event MyEventHandler SomeEvent;
// Этот метод вызывается для запуска события.
public void OnSomeEvent()
{
if (SomeEvent != null)
SomeEvent();
}
public object Clone()
{
MyEvent newMyEvent = (MyEvent)this.MemberwiseClone(); //Метод для копирования объектов значений
newMyEvent.name = String.Copy(name);
return newMyEvent;
}
}
//Класс содержащий событие
class EventDemo: ICloneable
{
public MyEvent evt = new MyEvent();
public EventDemo()
{
evt.SomeEvent += Handler; //присваиваем обработчик события
}
// Обработчик события.
void Handler()
{
Console.WriteLine("Событие произошло в объекте: " + evt.name);
}
public object Clone()
{
EventDemo newEventDemo = (EventDemo)this.MemberwiseClone(); //Метод для копирования объектов значений
newEventDemo.evt = (MyEvent)evt.Clone(); //Клонируем вложенный объект
return newEventDemo;
}
}
static void Main(string[] args)
{
//первый вариант
ObservableCollection<EventDemo> Collect = new ObservableCollection<EventDemo>() { new EventDemo(), new EventDemo()};
Collect[0].evt.name = "Объект 1";
Collect[0].evt.number = 1;
Collect[1].evt.name = "Объект 2";
Collect[1].evt.number = 2;
Console.WriteLine("Первый объект коллекции: " + Collect[0].evt.name+" Номер объекта: "+ Collect[0].evt.number);
Console.WriteLine("Второй объект коллекции: " + Collect[1].evt.name + " Номер объекта: " + Collect[1].evt.number);
foreach (EventDemo col in Collect)
{
col.evt.OnSomeEvent();
}
//второй вариант
Collect = new ObservableCollection<EventDemo>() { new EventDemo(), (EventDemo)Collect[0].Clone() };
Collect[0].evt.name = "Объект 1";
Collect[0].evt.number = 1;
Collect[1].evt.name = "Объект 2";
Collect[1].evt.number = 2;
Console.WriteLine("Первый объект коллекции: " + Collect[0].evt.name + " Номер объекта: " + Collect[0].evt.number);
Console.WriteLine("Второй объект коллекции: " + Collect[1].evt.name + " Номер объекта: " + Collect[1].evt.number);
foreach (EventDemo col in Collect)
{
col.evt.OnSomeEvent();
}
Console.ReadLine();
}
}
}
Answer the question
In order to leave comments, you need to log in
The MemberwiseClone method makes an incomplete copy of the object (ValueTypes are copied by value, but for reference types only a reference is copied), so in the second object you have a reference to the same MyEventHandler from the first object.
Try changing the right line from MemberwiseClone to just in the MyEvent.Clone method new MyEvent()
. But in the EventDemo.Clone method addevt.SomeEvent += Handler;
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question