簡體   English   中英

C#-如何從繼承的類型轉換為運行時類型

[英]C# - How to convert from inherited type to runtime type

我在運行時無法處理正確的類型。

我希望我的代碼根據參數類型動態檢測應調用哪個處理程序。 我不想將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()'方法起作用(我會假設)。

有許多通往羅馬的道路,並且有很多方法可以解決您的問題。 一種簡單的方法是為您的具體事件處理程序類型使用通用的抽象基類,該類可以提供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()約束,該約束僅允許使用可轉換的可實例化類型來用作通用類型參數)。 TEvent本身用作上面顯示的HandlerBase類的泛型類型參數,將導致兩個具有相同簽名的Handle方法,從而導致編譯錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM