泛型方法的可重用非泛型方法 [英] Reusable non generic method for generic methods

查看:104
本文介绍了泛型方法的可重用非泛型方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下基本接口:

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

以及继承基本接口的通用接口

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

我的类可以实现接口 IHandler< TMessage> 多次。 IMessage 是消息的基本接口,在这里不重要。

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

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

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

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

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

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


困扰我的是我必须实现处理(IMessage)方法,在我看来它的许多冗余代码,并且我必须在每次执行新的 IHandler< TMessage> 接口在我的类。



我正在寻找的是更通用的方式来实现 Handle (IMessage)方法(也许在处理程序的基类中),但我目前坚持如何做到这一点。

解决方案

您可以使用新的动态关键字将重载解析移至DLR:

  void IHandler.Handle(IMessage消息)
{
dynamic d = message;
手柄(d);

$ / code>

请注意,这会在运行时失败,出现 RuntimeBinderException 如果传入的消息对您的类无效。

为避免此异常,您可以为所有未知消息类型添加处理程序:

  private void Handle(object unknownMessage)
{
//在这里处理未知的消息类型。





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

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

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

protected virtual void HandleUnknownMessage(IMessage unknownMessage)
{
//在这里处理未知的消息类型。


code


$ b

你的特定处理程序看起来像这样:

  public class ExampleHandler:BaseHandler,
IHandler< ExampleMessage> ;,
IHandler< OtherExampleMessage>
{
public void Handle(ExampleMessage message)
{
// Handle ExampleMessage
}
$ b $ public void Handle(OtherExampleMessage message)
{
//在这里处理OtherExampleMessage
}
}



这段代码现在可以像这样工作:


  1. DLR调用通用的 BaseHandler.Handle< TMessage> / code>方法与真正的消息类型,即 TMessage 不会是 IMessage ,但具体的消息类例如 ExampleMessage

  2. 在这个Geneirc处理程序方法中,基类尝试将自身大小写为特定消息的处理程序。 li>
  3. 如果不成功,它会调用 HandleUnknownMessage 来处理未知的消息类型。转换成功,它在特定的消息处理程序上调用 Handle 方法,有效地将调用委托给具体的Handl er实现。


I have the following base interface

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

and an generic interface inheriting the base interface

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

My classes can implement the interface IHandler<TMessage> mutiple times. IMessage is an base interface for messages and isn´t relevant here. Currently i´m implementing the interfaces as follows.

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

What bothers me is the way i have to implement the Handle(IMessage) method, cause in my opinion its many redundant code, and i have to extend the method each time when i implement a new IHandler<TMessage> interface on my class.

What i´m looking for is a more generic way to implement the Handle(IMessage) method (maybe in a base class for Handlers), but i´m currently stuck how to do that.

解决方案

You can use the new dynamic keyword to move the overload resolution to the DLR:

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

Please note that this will fail at runtime with a RuntimeBinderException if the message passed in is not valid for your class.
To avoid this exception you can add a Handler for all unknown message types:

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


To implement IHandler.Handle in a base class, you need to do a little bit more work:

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

Your specific handler would than look like this:

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

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

This code now works like this:

  1. The DLR calls the generic BaseHandler.Handle<TMessage> method with the real message type, i.e. TMessage will not be IMessage but the concrete message class like ExampleMessage.
  2. In this geneirc handler method, the base class tries to case itself to a handler for the specific message.
  3. If that is not successful, it calls HandleUnknownMessage to handle the unknown message type.
  4. If the cast is successful, it calls the Handle method on the specific message handler, effectifly delegating the call to the concrete Handler implementation.

这篇关于泛型方法的可重用非泛型方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆