views:

185

answers:

4

Hi, I'm trying to break down the problem to a more simple description.

I'm using an external class library, which exposes 4 base classes, all very similar, sometimes derived from each other.

During the execution I'm called back on several delegate functions, all carrying an "object Sender", which contains the initial object of one of the 4 base classes, called on an API function before.

Sample (more or less pseudo code):

classA oA = new classA();
oA.API(callbackA);

Later on the callback is called, carrying oA as "Sender".

void callbackA(object Sender) {
  classA oA = (classA)Sender;
  oA.API2(xxx);
....
}

The approach above works fine. Now I wanted to extend it to the remaining 3 classes. Because the handling in their callbacks is rather identical, I didn't want to replicate the code another 3 times, but would rather make callbackA ready to deal with Senders of type classB, classC and classD.

I cannot achieve this in any usefull solution. Is anybody able to help me?

UPDATE: Because I did get lot of answer pointing to "is" - "is" is not a solution. I need to have ONE variable, capable of having multiple types. Dynamic casting?

A: 

You could have a look at is operator C#

The is operator is used to check whether the run-time type of an object is compatible with a given type.

Also, if these classes shared a common interface that would help you greatly.

astander
Comment see above. Of course I know about "is", but this doesn't give me ONE variable for all types.
neil
A: 

Found the solution. System.Reflection is it.

neil
+1  A: 

I'm assuming you aren't using a common interface because the class library is 'external' and you can't access the source. I'm also assuming that all of the possible concrete types for sender expose the same set of properties and methods--as far as your callback method is concerned.

Without a common base or interface you won't be able to avoid reflection or some conditional casting and repeated code. You can, however, encapsulate that code in a wrapper class. That would improve the readability of your callback method.

void callbackA(object sender)
{
    var wrappedSender = new MyWrapper(sender);
    wrappedSender.API2();
}

Again, assuming all sender classes are treated the same by your callback, you can use System.Reflection in your wrapper class to invoke the appropriate method (or access the appropriate properties). Using API2 as an example:

public class MyWrapper
{
    object _wrappedClass;
    public MyWrapper(object obj)
    {
        _wrappedClass = obj;
    }
    //...
    public void API2()
    {
        MethodInfo api2 = _wrappedClass.GetType().GetMethod("API2");
        api2.Invoke(_wrappedClass);
    }
    //...
}

This doesn't solve your problem exactly but it does separate the reflection 'plumbing' from your callback's intended behavior.

markalex
A: 

Using reflection for this is bad style, you should try to create a common interface for those classes and pass this to the delegate. If this is not possible then wrap the classes into wrappers which share an interface, i.e.:

interface IMyDelegate {
  public void HandleCallback();
}


class WrapperA : IMyDelegate {
  private ClassA classA;
  public WrapperA(ClassA classA) {this.classA = classA;}
  public void HandleCallback()
  {
     /* ... your callback code here ... */
  }
}

Same for ClassB, ClassC and ClassD.

Then you pass it to the Callback and cast it to the interface:

void callback(object sender) {
  IMyDelegate caller = (IMyDelegate)sender;
  caller.HandleCallback();
}
dbemerlin
Hmm. Thanks for the hint, which seem to not meet my demands. In order to illustrate, what I need, here is some sample code and my current solution: http://maps.alphadex.de/eldos/comment1.txt
neil