1

I have an architectural question for my WinForms, C# based application. I really hope somebody can give me an idea of how to solve this.

I have different classes implementing the interfaces ITest1 or ITest2 or both.

class1 : ITest1
class2 : ITest1, ITest2
class3 : ITest2

At the start of the application I have some configuration source that tells the application what classes to use during the entire lifetype of the application(class1, class2 or class3) for ITest1 and ITest2

ITest1 test1;
ITest2 test2;
switch (configresult)
{
    case "configuration1":
        test1 = new class1();
        test2 = new class2();
        break;
    case "configuration2":
        test1 = new class2();
        test2 = new class3();
        break;
    case "configuration3":  // This happens the most!
        test1 = new class2();
        test2 = (class2)test1;
        break;
}

Now I would like to know during runtime what class implements the certain interface. In pseudocode:

if( test1 is implemented by class2 )
    ((class2)test1).Class2Method();

if( test2 is implemented by class1 )
    ((class1)test1).Class1Method();

Is there a way to find out the class used to implement an interface by having the interface variable available?

In the real program I have over 10 interfaces that are implemented by 40+ classes in completely different ways, so I would not like to do any switch statements for all moments I need to cast back to the original class.

------------------UPDATE!

I guess some background info makes it easier to get my problem and yes I agree with Ed S. that it is more a question about my design, but I am very much willing to change it all.

My scientific application supports over 40+ different scientific instruments to measure semiconductors. Temperaure, current, voltage, switches, you name it. I defined 10 functionalities that are available to the user: temperature, voltage, current,switching, etc.... These are all put in interfaces; ITemperature, IVoltage, etc...

Some instruments can do everything and some can only do parts. If the user has a supported high quality temperature measurement device, we use that to implement ITemperature, however when he/she has an expensive voltmeter that also can measure a temperture I use the same instrument to measure Temperature and Voltage (so the instrument implements ITemperature and IVoltage). All instruments are very, very different, it is hardly possible to make one abstract class to cover them all. Some need to be controlled over a webinterface, some over usb and believe me many things are different. So sometimes I need to access the instrument class directly (to reset a register, initialize or whatever). This is what I try to do. Any suggestion is very very welcome.

Enrico
  • 1,937
  • 3
  • 27
  • 40
  • 3
    Why would you need to cast back to the actual implementation? Isn't that what you were trying to avoid by having those interfaces? You could determine the Type with just a GetType(), but i'm wondering why this would be necessary. – Pablo Romeo Dec 11 '12 at 20:38
  • 1
    Possible duplicate of http://stackoverflow.com/q/1159906 – Robert Harvey Dec 11 '12 at 20:38
  • 1
    Sounds like a poor design in general and a slight misunderstanding of how to use interfaces and (possibly) polymorphism. You are asking how to solve your *proposed implementation issue*, not an architectural problem. What is the actual problem you are trying to solve with this? – Ed S. Dec 11 '12 at 20:38
  • Sounds like you should re-think your design. Consider adding another interface for that method. – SLaks Dec 11 '12 at 20:40
  • Ed S., SLaks, Pablo thanks I wrote down more background info. Any suggestions for patterns to use are very welcome.... – Enrico Dec 11 '12 at 20:53
  • I know that your code is an example and hopefully not reflective of the quality of your real code, but the cast to `Class2` in your `Configuration3` is redundant as a `Class2` object is already a `ITest2` object. Also it seems a bit unusual that unlike your other Configuratins you are only using one object in `Configuration3` as both `test2` and `test1` point to the same object.(But hey I don't know your code!). – DeanOC Dec 11 '12 at 20:57
  • possible duplicate of [Finding the Concrete Type behind an Interface instance](http://stackoverflow.com/questions/1159906/finding-the-concrete-type-behind-an-interface-instance) – Steve Dec 11 '12 at 21:03

5 Answers5

2

There's the is keyword documented here although it sounds like from your question you've got bigger problems in your architecture.

if( test1 is class2 )
    ((class2)test1).Class2Method();

if( test2 is class1 )
    ((class1)test1).Class1Method();
McAden
  • 13,714
  • 5
  • 37
  • 63
1
if (test1.GetType() == typeof(class2)) ...

Or alternatively:

var c = test1 as class2;
if (c != null) c.Class2Method();
Joe
  • 122,218
  • 32
  • 205
  • 338
  • Approach 1 wont work, and aproach 2 does not take into account that test1 might already be null. – Johny Skovdal Dec 11 '12 at 20:42
  • @JohnySkovdal, care to elaborate? Approach 1 does not take account that test1 might be null - the OP didn't ask for it and it's easy to add. But Approach 2 does: if test1 is null, then so is c, and there is a null check. – Joe Dec 11 '12 at 22:05
  • Ah, sorry, I read the original question wrong, and thought he was looking to find the interface, and `GetType()` would not find the interface, so approach 1 does indeed work, my bad. As for approach 2, I was referring to if test1 is null, that might make the OP conclude something wrong, which is what I have against the `as` keyword. E.g. he might make the following code based on that: `var a=test1 as class1;var b=test1 as class2;if(a!=null){//}else if(b!=null){//}else{((Class3)test1).Class3Method();}`, so my objection with approach 2 was more of a warning against using it wrong. – Johny Skovdal Dec 12 '12 at 07:12
1

I think what you're really looking for is Duck Typing, not casting. Casting is pretty much a compile-time activity. You can implement duck typing with a library, or with C# 4.0's dynamic keyword.

public static dynamic Quack(dynamic duck)
{
    try
    {
        // bind method at run time and execute it
        return duck.Quack();
    }
    catch (RuntimeBinderException)
    {
        //throw if method call failed
        return null;
    }        
}

You can cast at runtime and call methods on the cast, but it uses Reflection, and is not terribly fast. See here.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
1

You don't need to know which class implements an interface. Instead, you can access the desired functionality directly through the interface. That's what the interfaces are for.

ITest1 test1 = obj as ITest1;
if (test1 != null) {
    test1.Test1InterfaceMethod();
}

ITest2 test2 = obj as ITest2;
if (test2 != null) {
    test2.Test2InterfaceMethod();
}

The as keyword has the advantage over casting that testing for the type and casting are only one operation. Otherwise you have to test for the type with is and then cast with (), what internally tests again for the type :-(

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thanks, but this I know, it is about calling the method of a class that also implements an interface... – Enrico Dec 13 '12 at 20:23
0

Use the GetType() method of the object you want to test.

Brahim Boulkriat
  • 984
  • 2
  • 9
  • 21