c# - 泛型方法的可重用非泛型方法

标签 c# generics interface

我有以下基本接口(interface)

public interface IHandler{
  void Handle(IMessage message);
}

以及继承基接口(interface)的通用接口(interface)

public interface IHandler<TMessage> : IHandler where TMessage : IMessage{
  void Handle(TMessage message);
}

我的类可以实现接口(interface)IHandler<TMessage>多次。 IMessage是消息的基本接口(interface),与此处无关。目前我正在实现如下接口(interface)。

public class ExampleHandler : IHandler<ExampleMessage>, IHandler<OtherExampleMessag>{

  void IHandler.Handle(IMessage message){
    ExampleMessage example = message as ExampleMessage;

    if (example != null) {
      Handle(example);
    }
    else {
      OtherExampleMessage otherExample = message as OtherExampleMessage;

      if (otherExample != null) {
        Handle(otherExample);
      }
  }

  public void Handle(ExampleMessage) {
   //handle message;
  }

  public void Handle(OtherExampleMessage) {
   //handle message;
  }
}

令我困扰的是我必须实现 Handle(IMessage) 的方式方法,因为在我看来它有很多冗余代码,并且每次当我实现新的IHandler<TMessage>时我都必须扩展该方法。我的类(class)界面。

我正在寻找的是一种更通用的方法来实现 Handle(IMessage)方法(可能在处理程序的基类中),但我目前不知道如何做到这一点。

最佳答案

您可以使用新的 dynamic关键字将重载决策移至 DLR:

void IHandler.Handle(IMessage message)
{
    dynamic d = message;
    Handle(d);
}

请注意,这将在运行时失败,并显示 RuntimeBinderException如果传入的消息对您的类(class)无效。
为了避免这种异常,您可以为所有未知消息类型添加处理程序:

private void Handle(object unknownMessage)
{
    // Handle unknown message types here.
}

实现IHandler.Handle在基类中,您需要做更多的工作:

public class BaseHandler : IHandler
{
    void IHandler.Handle(IMessage message)
    {
        dynamic d = message;
        Handle(d);
    }

    private void Handle<TMessage>(TMessage message) where TMessage : IMessage
    {
        var handler = this as IHandler<TMessage>;
        if(handler == null)
            HandleUnknownMessage(message);
        else
            handler.Handle(message);
    }

    protected virtual void HandleUnknownMessage(IMessage unknownMessage)
    {
        // Handle unknown message types here.
    }
}

您的特定处理程序将如下所示:

public class ExampleHandler : BaseHandler,
                              IHandler<ExampleMessage>,
                              IHandler<OtherExampleMessage>
{
    public void Handle(ExampleMessage message)
    {
        // handle ExampleMessage here
    }

    public void Handle(OtherExampleMessage message)
    {
        // handle OtherExampleMessage here
    }
}

此代码现在的工作方式如下:

  1. DLR 调用通用 BaseHandler.Handle<TMessage>具有真实消息类型的方法,即 TMessage不会IMessage但具体的消息类如 ExampleMessage .
  2. 在此通用处理程序方法中,基类尝试将自身设置为特定消息的处理程序。
  3. 如果不成功,则会调用 HandleUnknownMessage处理未知的消息类型。
  4. 如果转换成功,它会调用 Handle特定消息处理程序上的方法,有效地将调用委托(delegate)给具体的处理程序实现。

关于c# - 泛型方法的可重用非泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12855930/

相关文章:

java - 方法应该返回 Class 还是 Class<?>?

c# - .NET 运行时处理通用代码

java - 在java 8中,为什么无法调用当前类正在实现的接口(interface)静态方法

c# - 在 C# 中创建接口(interface)实例

c# - 单独的动画有效, Storyboard 无效。为什么?

c# - cookie 过期后如何返回 401 状态而不是 302 重定向?

java - 使用 Java 8 中的供应商用泛型列表填充数组抛出删除类型的 ClassCastEx b/c

c# - 是否可以消除由于接口(interface)引起的 DLL 依赖?

c# - 在 DataGridView 的单元格内显示图标和字符串

c# - 将字典转换为 C# 中的对象列表