【问题标题】:c#: Variable types in delegatec#:委托中的变量类型
【发布时间】:2011-01-16 22:51:35
【问题描述】:

我正在尝试将问题分解为更简单的描述。

我正在使用一个外部类库,它公开了 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 类型的 Sender。

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

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

【问题讨论】:

  • 这些类有共同的接口吗?
  • 至少他们声称,B 是 A 的后代......

标签: c# function variables types


【解决方案1】:

你可以看看is operator C#

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

此外,如果这些类共享一个通用接口,那将对您有很大帮助。

【讨论】:

  • 评论见上文。我当然知道“is”,但这并没有给我一个适用于所有类型的变量。
【解决方案2】:

类似:

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 的公共基类或接口时,它会变得更有效率。

【讨论】:

  • 如果它会那么容易......正如我所说:我不想一遍又一遍地重复编写相同的代码。通过您的方法,我将获得 n 个不同类型的变量。我需要一个变量,能够处理多种类型。
  • @neil: 为此你需要一个通用的基类/接口
【解决方案3】:

我假设您没有使用通用接口,因为类库是“外部”的,您无法访问源代码。我还假设 sender 的所有可能的具体类型都公开了相同的属性和方法集——就您的回调方法而言。

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

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);
    }
    //...
}

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 嗯。感谢您的提示,这似乎不符合我的要求。为了说明,我需要什么,这里是一些示例代码和我当前的解决方案:maps.alphadex.de/eldos/comment1.txt
    猜你喜欢
    • 2020-03-05
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2011-04-09
    相关资源
    最近更新 更多