C # - Как преобразовать из унаследованного типа в тип времени выполнения - PullRequest
0 голосов
/ 04 июля 2018

У меня проблемы с обработкой правильного типа во время выполнения.

Я хочу, чтобы мой код динамически определял, какой обработчик должен вызываться на основе типа параметра. Я не хочу приводить 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 голосов
/ 04 июля 2018

Есть много дорог, которые ведут в Рим, и есть немало способов, которыми вы можете решить свою проблему. Один простой подход заключается в использовании общего абстрактного базового класса для ваших конкретных типов обработчиков событий, который может обеспечить метод 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 как абстрактный класс или превратите его в интерфейс (обратите внимание на ограничение new(), которое я использовал для HandlerBase выше, что позволяет использовать только конкретные, инстанцируемые типы в качестве параметра универсального типа). Использование самого TEvent в качестве параметра общего типа для класса HandlerBase, показанного выше, приведет к двум методам Handle с одинаковой сигнатурой, что приведет к ошибке компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...