C#-如何从继承的类型转换为运行时类型

时间:2018-07-04 07:59:53

标签: c# reflection

我在运行时无法处理正确的类型。

我希望我的代码根据参数类型动态检测应调用哪个处理程序。我不想在代码中将TEvent转换为正确的类型。

所有处理程序都从我的界面继承:

public interface IAbstractHandler < in T>  
{
   void Handle(T evnt);
}

示例:

public class SpecificEventHandler: IAbstractHandler< SpecificEvent>
{
   public void Handle(SpecificEvent evnt) {
    ....
   }
}

TEvent.cs:

public class TEvent
{
}

处理程序中使用的所有其他事件均来自TEvent。

以下是一些代码:

List<TEvent> eventItems = new List<TEvent>();
....
foreach (var evt in eventItems) {
  ...
  dynamic eventHandler = ResolveEventHandler(evt.GetType().Name);
  if (evt is MySubtypeEvent subEvent) {
    eventHandler.Handle(subEvent); // <-- this works, but I don't want this.
  }
  eventHandler.Handle(evt); // <-- And this fails, because 'evt' is seemingly 
  // a TEvent even though it's of the correct subclass.
}

我正在寻找一种使'evt'不是TEvent而是真实类型的方法,但是如果不对其进行硬编码,这将使我的'eventHandler.Handle()'方法起作用(我会假设)。

1 个答案:

答案 0 :(得分:1)

通向罗马的道路很多,有很多方法可以解决您的问题。一种简单的方法是为您的具体事件处理程序类型使用通用的抽象基类,该类可以提供Handle(TEvent evt)方法。

public abstract class HandlerBase<T> where T : TEvent, new()
{
    public abstract void Handle(T evt);


    public void Handle(TEvent evt)
    {
        if (!(evt is T))
        {
            throw new ArgumentException("This handler does not support the event type " + evt.GetType().FullName); 
        }

        Handle((T) evt);
    }
}

您的特定事件处理程序将从该抽象基类派生,类似于此代码示例:

public class SpecificEventHandler: HandlerBase<SpecificEvent>
{
   public override void Handle(SpecificEvent evnt)
   {
      ....
   }
}


然后可以将您问题中的代码简化为:

foreach (var evt in eventItems)
{
    ...
    dynamic eventHandler = ResolveEventHandler(evt.GetType().Name);
    eventHandler.Handle(evt);
}


此外,要禁止使用TEvent本身作为通用类型参数来指定事件处理程序,请将TEvent声明为抽象类或将其转换为接口(请注意我用于 HandlerBase <的new()约束。 / em>,仅允许将可实例化的类型用作通用类型参数。将TEvent本身用作上面显示的HandlerBase类的泛型类型参数,将导致两个具有相同签名的 Handle 方法,从而导致编译错误。