简体   繁体   中英

change C# object to type decided at run-time

The problem

I have a WinForms program that has to talk to different pieces of hardware using different connection types such as TCP, USB, etc. Using the connections entails using a common set of actions provided by VISA (such as open, read, write, close). How data is passed to these functions or any transforms that might need to be applied to the data before or after use would vary by connection type.

The connections are used to connect to different pieces of hardware when some method decides that a particular hardware operation requires a type of certain connection (specified by some other data).

At some point in the future I might like to add more types of connections.

A user of the application can select and edit a connection part of which entails changing the connection type (ie change from using TCP to using USB). Changing the type means different method implementations will be used to operate the physical connection. It is this change of type when editing a connection that I am working on.

The data related to each connection (including type data) is persisted via an external data source.

My solution so far

I have an abstract class Connection with some derived types such as Tcp , Usb , etc, they have common methods and properties from the abstract class (eg Address , Open() , etc) but the implementations differ to get the different data and address formats in the correct format for the VISA interface.

The application starts by populating a List<Connection> from the source of data. On this List are objects of the types derived from Connection .

To present the user with controls to allow the changing of type when one of the connections from the list is selected but still keep the usage generalised the form has RadioButton controls that are created by a method that uses reflection to find generate one object of each of the derived classes and adds the names of them to the form, with a common CheckedChanged event handler .

For example:

ConnectionIEnumerable = GetObjectsDerivedFromType<Connection>();
foreach (Connection c in ConnectionIEnumerable)
{
     var rb = new RadioButton();
     rb.Name = c.ToString() + "RadioButton";
     rb.CheckedChanged += new EventHandler(CommonEventHandler);
     form1.flowLayoutPanel1.Controls.Add(rb);
}

Where I'm stuck

How can this generic handler that is used "know" what type to convert the currently selected object to? How does the RadioButton store and impart the information about a related type that should be converted to?

I've looked at trying this plan other ways but it always comes back to a requirement that at some point there would need to be some kind of if checking the current type to convert it, or checking the type to be converted to, thus introducing non-generality.

I think the OOP encapsulation way of doing this would be to somehow associate type information with each RadioButton as it's created and have the types themselves define how to convert between them but I'm not sure if this is correct, or of the best way of doing this; use cast overrides, a type converter, IConvertible , etc. Such that the handler could use something like (for example only) the below, to replace the object on the List:

    currentObject.ConvertTo( (Type)( (RadioButton)sender).Tag ) );

Update:

For anyone with a similar quandary I took Patrick Hoffman's answer and saved type information to the RadioButton.Tag like so:

rb.Tag = c.GetType()

Then used it in the handler like:

EditedConnection = (Connection)Activator.CreateInstance((Type)((RadioButton)sender).Tag);

How can this generic handler that is used "know" what type to convert the currently selected object to?

It shouldn't need to know that. If your program solely depends on the abstract base class, the only think you need to do is instantiate the type once, and use the base class throughout your program.

If you need to construct an instance, Activator.CreateInstance(Type) is what you need. You could retrieve the type from the reflection you did before to populate the list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM