c#:委托中的变量类型

时间:2010-02-15 11:11:50

标签: c# function variables types

我试图将问题分解为更简单的描述。

我正在使用一个外部类库,它暴露了4个基类,它们都非常相似,有时相互派生。

在执行期间,我回调了几个委托函数,它们都带有一个“对象发送者”,它包含4个基类之一的初始对象,之前调用了API函数。

示例(或多或少的伪代码):

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

稍后调用回调,将oA作为“发件人”。

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

上述方法运行正常。现在我想将它扩展到剩下的3个类。因为它们的回调中的处理非常相同,所以我不想再将代码复制3次,而是希望使callbackA能够处理类型为classB,classC和classD的发送者。

我无法在任何有用的解决方案中实现这一点。有人能帮助我吗?

更新:因为我确实得到了很多指向“是”的答案 - “是”不是解决方案。我需要有一个变量,能够有多种类型。动态铸造?

4 个答案:

答案 0 :(得分:1)

类似的东西:

void callbackA(object Sender) 
{
  if (sender is ClassA)
  {
    classA oA = (classA)Sender;
    oA.API2(xxx);
  }
  else if (sender is ClassB)
  {
    classB oB = (classB)Sender;
    oB.API2(xxx);
  }

  ....
}

当您可以使用A和B的公共基类或接口时,它会变得更有效率。

答案 1 :(得分:1)

我假设您没有使用通用接口,因为类库是“外部”而您无法访问源。我还假设发件人的所有可能的具体类型都暴露了相同的属性和方法集 - 就你的回调方法而言。

如果没有通用的基础或界面,您将无法避免反射或某些条件转换和重复代码。但是,您可以将该代码封装在包装类中。这将提高回调方法的可读性。

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

同样,假设您的回调对所有发送者类的处理方式相同,您可以在包装器类中使用System.Reflection来调用适当的方法(或访问适当的属性)。以API2为例:

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

这并不能完全解决您的问题,但它确实将反射'管道'与回调的预期行为分开。

答案 2 :(得分:0)

您可以查看is operator C#

  

is运算符用于检查   是否为对象的运行时类型   与给定类型兼容。

此外,如果这些类共享一个可以帮助你的公共接口。

答案 3 :(得分:0)

对此使用反射是不好的样式,您应该尝试为这些类创建一个公共接口并将其传递给委托。如果这是不可能的,那么将类包装成共享接口的包装器,即:

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 ... */
  }
}

同样适用于ClassB,ClassC和ClassD。

然后将它传递给Callback并将其转换为界面:

void callback(object sender) {
  IMyDelegate caller = (IMyDelegate)sender;
  caller.HandleCallback();
}