1

我对基于 C# 的 WinForms 应用程序有一个架构问题。我真的希望有人能给我一个如何解决这个问题的想法。

我有不同的类实现接口 ITest1 或 ITest2 或两者。

class1 : ITest1
class2 : ITest1, ITest2
class3 : ITest2

在应用程序开始时,我有一些配置源告诉应用程序在 ITest1 和 ITest2 的整个应用程序生命类型(class1、class2 或 class3)中使用哪些类

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;
}

现在我想知道在运行时哪个类实现了某个接口。在伪代码中:

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

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

有没有办法通过提供接口变量来找出用于实现接口的类?

在实际程序中,我有 10 多个接口,这些接口由 40 多个类以完全不同的方式实现,所以我不想在需要转换回原始类的所有时刻都执行任何 switch 语句。

- - - - - - - - - 更新!

我想一些背景信息可以更容易地解决我的问题,是的,我同意 Ed S. 这更多的是关于我的设计的问题,但我非常愿意改变这一切。

我的科学应用程序支持 40 多种不同的科学仪器来测量半导体。温度、电流、电压、开关,应有尽有。我定义了 10 个可供用户使用的功能:温度、电压、电流、开关等……这些都放在接口中;ITemperature、IVoltage 等...

有些乐器可以做任何事情,有些只能做部分。如果用户有支持的高质量温度测量设备,我们使用它来实现 ITemperature,但是当他/她有一个昂贵的电压表也可以测量温度时,我使用相同的仪器来测量温度和电压(因此仪器实现 ITemperature和电压)。所有仪器都非常非常不同,几乎不可能创建一个抽象类来涵盖所有仪器。有些需要通过网络界面进行控制,有些需要通过 USB 进行控制,相信我很多事情都不同。所以有时我需要直接访问仪器类(重置寄存器、初始化或其他)。这是我尝试做的。非常欢迎任何建议。

4

5 回答 5

2

此处记录了is关键字,尽管从您的问题中听起来您的架构中存在更大的问题。

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

if( test2 is class1 )
    ((class1)test1).Class1Method();
于 2012-12-11T20:40:20.330 回答
1

您不需要知道哪个类实现了接口。相反,您可以直接通过界面访问所需的功能。这就是接口的用途。

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

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

与强制转换相比,as关键字的优势在于类型测试和强制转换只是一种操作。否则,您必须测试类型,is然后强制()转换,内部再次测试类型:-(

于 2012-12-11T22:09:05.440 回答
1

我认为您真正要寻找的是 Duck Typing,而不是铸造。铸造几乎是一个编译时活动。您可以使用library或使用 C# 4.0 的dynamic关键字来实现鸭子类型。

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;
    }        
}

您可以在运行时进行投射并在投射时调用方法,但它使用反射,并且速度不是非常快。见这里

于 2012-12-11T21:54:48.603 回答
1
if (test1.GetType() == typeof(class2)) ...

或者:

var c = test1 as class2;
if (c != null) c.Class2Method();
于 2012-12-11T20:36:12.627 回答
0

使用要测试的对象的 GetType() 方法。

于 2013-10-18T10:27:42.347 回答