How to clone a refrenced type object?

H

Hamed

Hello

I am developing a utility to be reused in other programs. It

I have an object of type Control (a TextBox, ComboBox, etc.) that other
programmers use it in applications. they may set some of properties or
assign event handlers. I need to be able to clone the manipulated control at
runtime.

I could use the Clone method of some objects (like Font, Style, String,
etc..) but the controls like Button, TextBox, ListBox doesn't have this kind
of method.


How can I create a clone of an object instance for controls like TextBox,
ListBox, ListViews, CheckBox ??


Any help is appreciated,
 
H

Hamed

Hello

It seems that I should implement ICloneable to implement my own clone
object. the critical point for me is to make a control object based on
another control object that all of its event handlers are set like the old
one. Is there a way to do this job?

For example, is there a way to use EventInfo object to get all event
handlers of the old control in runtime and set my new cloned control events
to the event handlers of the old control?

Any suggestion is appreciated.

Regards
Hamed
 
M

Marc Gravell

The problem is that the EventInfo gives you info about the accessor,
bot the backing field - i.e. typically:

private EventHandler someEvent; // this is what we want
public event EventHandler SomeEvent { // this is what EventInfo reports
add {someEvent += value;}
remove {someEvent -= value;}
}

note: the compiler does this for you if you type:

public event EventHandler SomeEvent;

(noting that the name of the field can't be relied upon). So if you own
the Control and that specifc event, then you can do it easily as you
have visibility of the backing delegate field, but for external
Controls, or events in sub-classes, it is much harder. You would pretty
much need to walk the private fields.

Also: you should only really be cloning those event-handlers that you
own, since other code (than yours) my be subscribing that isn't
expecting that call (e.g. databinding implementations, etc).

My best advice normally is to simply re-apply the event handler s that
you know about, presumably in the same block of code that you use to
set the originals up in the first place (which probably means *not* the
designer-generated code). In your case, this may not be possible (due
to not being the setter-upper of the events); perhaps a bit of
misdirection would be in order? i.e. your code subscribes to the events
of all the controls, and their code subscribes to yours? And your code
manages the Clone operation, such that you can subscribee your code to
the Control's events... possibly... I think it could get very messy,
though...

Marc
 
H

Hamed

Marc
Thanks for your comment. But the problem is:

I have a control that use in a DataGridColumnStyle of my own. I want to give
the programmer the ability to assign its own event handlers. then there is
another column that needs a control exactly as previous (at least its events
are the same) and I need to clone the control. so I should at least copy the
properties and event handlers in the new control.

So I need to somehow copy them in the Clone method that is come from
ICloneable interface of my control's class.

Now how can I make a new control (suppose a TextBox from a class
MyOwnTextBox) that copies its properties and events?

Regards
Hamed
 
M

Marc Gravell

Again - it depends if you own the events; this could be as simple as:

public MyTextBox Clone() {
MyTextBox tb = new MyTextBox(); // include anthing in the ctor that
is "readonly"
// fields and properties that we want to copy...
tb.PropertyA = this.PropertyA; // if accessible etc
tb.fieldB = this.fieldB; // declared in this type (not in a
base-class), or protected
tb.eventBackerC = this.eventBackerC; // declared in this type (not in
a base-class)
tb.SimpleEventD = this.SimpleEventD; // declared in this type (not in
a base-class)
}

If you *don't* own them (i.e. declared in a base class, and no
protected access), then you need to either a: (preferably) rethink the
design, or b: use field-level reflection.

Let me know if I missed the point....

Marc
 
H

Hamed

I don't understand the meaning of
tb.eventBackerC = this.eventBackerC; // declared in this type (not in a
base-class)
tb.SimpleEventD = this.SimpleEventD; // declared in this type (not in a
base-class)

There is some event handlers assigned in other classes for example for Click
event. I want the cloned control to point to the event handler methods of
the old control. How to do this job?

Regards.
Hamed
 
J

john sun

I think what you need here is probably not the clone() method, instead,
you probably want to declare your control as a base class, so other
people can inherit from them.

Then, you declare the event handler as protected methods, the new
control inherited from it can just simply override it.
 
H

Hamed

No. I have a several controls as fields in a container. In different
situations, some of them should be cloned. I just want a clone method that
accepts to clone the events too. :-(
 
N

Nicholas Paldino [.NET/C# MVP]

Hamed,

Ultimately, you can't do it reliably.

If the method that is creating the clone is a member of the class being
cloned, then you can simply do:

// Inside clone method.
MyClass clone = new MyClass();
clone.MyEvent += this.MyEvent;

This assumes that you are declaring an event using the event keyword,
and not using add/remove handlers. It works because the C# compiler creates
a backing field of the same name (MyEvent).

However, if you declare your event like this:

private EventHandler myEventHandler;

public event EventHandler MyEvent
{
add
{
myEventHandler += value;
}
remove
{
myEventHandler -= value;
}
}

Then the call to assign the event will fail, because the compiler will
not see the backing field that has the delegate in it, and revert to that.

Even if you are making the call from outside the type, the same problem
exists, since there is nothing on the metadata that links the event to the
backing field. There is nothing in the metadata that says that the backing
field has to be connected to the event. It's like asking for metadata on a
property, and then asking what the backing field is (or multiple backing
fields, since properties can really return anything they want, just like
event handlers).

So, that being said, there really isn't a reliable way to do this. The
best you could do is have an interface (if you plan on doing this across
multiple types) which would return a mapping of events to handlers, and then
when you clone the object, you would get those delegates and then perform
the clone.

Hope this helps.
 
H

Hamed

Nicholas

The method that is creating the clone is a member of the class being cloned.
I want for example to assign the Click event of the control of my own to the
new cloned object. but when I tried your solution I got compiler error. for
example:

public class MyTextBox : TextBox, ICloneable
{
public object Clone()
{
MyTextBox clone = new MyTextBox();
clone.Click += this.Click; //compiler error!
The event '....Click' can only appear on the left hand side of += or -=
}
}

Would you kindly describe your suggestion more?

Best Regards
Hamed


Nicholas Paldino said:
Hamed,

Ultimately, you can't do it reliably.

If the method that is creating the clone is a member of the class being
cloned, then you can simply do:

// Inside clone method.
MyClass clone = new MyClass();
clone.MyEvent += this.MyEvent;

This assumes that you are declaring an event using the event keyword,
and not using add/remove handlers. It works because the C# compiler
creates a backing field of the same name (MyEvent).

However, if you declare your event like this:

private EventHandler myEventHandler;

public event EventHandler MyEvent
{
add
{
myEventHandler += value;
}
remove
{
myEventHandler -= value;
}
}

Then the call to assign the event will fail, because the compiler will
not see the backing field that has the delegate in it, and revert to that.

Even if you are making the call from outside the type, the same problem
exists, since there is nothing on the metadata that links the event to the
backing field. There is nothing in the metadata that says that the
backing field has to be connected to the event. It's like asking for
metadata on a property, and then asking what the backing field is (or
multiple backing fields, since properties can really return anything they
want, just like event handlers).

So, that being said, there really isn't a reliable way to do this. The
best you could do is have an interface (if you plan on doing this across
multiple types) which would return a mapping of events to handlers, and
then when you clone the object, you would get those delegates and then
perform the clone.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Hamed said:
Hello

It seems that I should implement ICloneable to implement my own clone
object. the critical point for me is to make a control object based on
another control object that all of its event handlers are set like the
old one. Is there a way to do this job?

For example, is there a way to use EventInfo object to get all event
handlers of the old control in runtime and set my new cloned control
events to the event handlers of the old control?

Any suggestion is appreciated.

Regards
Hamed
 
H

Hamed

I found the following link in the net. But it seems it has left the solution
unfinished.

http://www.dotnet247.com/247reference/msgs/58/293131.aspx

This message was discovered on microsoft.public.dotnet.languages.csharp.

the question is if we know that we want to find all subscribed methods of
Click event how could we do the job?

(Take a look to the following code)
public class MyTextBox : TextBox, ICloneable
{
public object Clone()
{
MyTextBox clone = new MyTextBox();
clone.Click += this.Click; //compiler error!
The event '....Click' can only appear on the left hand side of += or -=
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Hamed,

You can't copy the events reliably. If you look at the definition of
the Click event in the TextBoxBase class, you will see the reason it fails
when you try and assign the event to the new clone (it defines custom event
handlers).


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Hamed said:
Nicholas

The method that is creating the clone is a member of the class being
cloned. I want for example to assign the Click event of the control of my
own to the new cloned object. but when I tried your solution I got
compiler error. for example:

public class MyTextBox : TextBox, ICloneable
{
public object Clone()
{
MyTextBox clone = new MyTextBox();
clone.Click += this.Click; //compiler error!
The event '....Click' can only appear on the left hand side of += or -=
}
}

Would you kindly describe your suggestion more?

Best Regards
Hamed


Nicholas Paldino said:
Hamed,

Ultimately, you can't do it reliably.

If the method that is creating the clone is a member of the class
being cloned, then you can simply do:

// Inside clone method.
MyClass clone = new MyClass();
clone.MyEvent += this.MyEvent;

This assumes that you are declaring an event using the event keyword,
and not using add/remove handlers. It works because the C# compiler
creates a backing field of the same name (MyEvent).

However, if you declare your event like this:

private EventHandler myEventHandler;

public event EventHandler MyEvent
{
add
{
myEventHandler += value;
}
remove
{
myEventHandler -= value;
}
}

Then the call to assign the event will fail, because the compiler will
not see the backing field that has the delegate in it, and revert to
that.

Even if you are making the call from outside the type, the same
problem exists, since there is nothing on the metadata that links the
event to the backing field. There is nothing in the metadata that says
that the backing field has to be connected to the event. It's like
asking for metadata on a property, and then asking what the backing field
is (or multiple backing fields, since properties can really return
anything they want, just like event handlers).

So, that being said, there really isn't a reliable way to do this.
The best you could do is have an interface (if you plan on doing this
across multiple types) which would return a mapping of events to
handlers, and then when you clone the object, you would get those
delegates and then perform the clone.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)


Hamed said:
Hello

It seems that I should implement ICloneable to implement my own clone
object. the critical point for me is to make a control object based on
another control object that all of its event handlers are set like the
old one. Is there a way to do this job?

For example, is there a way to use EventInfo object to get all event
handlers of the old control in runtime and set my new cloned control
events to the event handlers of the old control?

Any suggestion is appreciated.

Regards
Hamed



Hello

I am developing a utility to be reused in other programs. It

I have an object of type Control (a TextBox, ComboBox, etc.) that other
programmers use it in applications. they may set some of properties or
assign event handlers. I need to be able to clone the manipulated
control at runtime.

I could use the Clone method of some objects (like Font, Style, String,
etc..) but the controls like Button, TextBox, ListBox doesn't have this
kind
of method.


How can I create a clone of an object instance for controls like
TextBox,
ListBox, ListViews, CheckBox ??


Any help is appreciated,
 
N

Nicholas Paldino [.NET/C# MVP]

Hamed,

Actually, this thread and that thread are pretty much exactly the same.
There is no reliable way to do this.
 
H

Hamed

Nicholas,

I appreciate your comments. thanks to pay attention. but:

When you say there is no reliable way, does this mean there may be some
unreliable ways?

Hamed


Nicholas Paldino said:
Hamed,

Actually, this thread and that thread are pretty much exactly the same.
There is no reliable way to do this.
 
H

Hamed

Thanks for your kind attention.

Of course, I found some solutions using Reflection. It works perfectly but
the solution is messy

Thanks a lot and Regards.





-----Original Message-----

From: Nicholas Paldino [.NET/C# MVP] [mailto:[email protected]]

Sent: Sunday, August 13, 2006 5:19 PM

To: (e-mail address removed)

Subject: Re: How to clone event handlers

Hamed,

Actually, this thread and that thread are pretty much exactly the same.

There is no reliable way to do this.



--

- Nicholas Paldino [.NET/C# MVP]

- (e-mail address removed)

I found the following link in the net. But it seems it has left the
solution unfinished.



This message was discovered on
microsoft.public.dotnet.languages.csharp.


the question is if we know that we want to find all subscribed methods
of

Click event how could we do the job?

(Take a look to the following code)
+=

of my
own to the new cloned object. but when I tried your solution I got
compiler error. for example:

public class MyTextBox : TextBox, ICloneable {
public object Clone()
{
MyTextBox clone = new MyTextBox();
clone.Click += this.Click; //compiler
error! The event '....Click' can only appear on the left hand side of
+=
or -=
}
}

Would you kindly describe your suggestion more?

Best Regards
Hamed


"Nicholas Paldino [.NET/C# MVP]" <[email protected]>
wrote
keyword,
revert
the
says
return
this.
this
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top