Вызов метода на универсальном контравариантном интерфейсе - PullRequest
0 голосов
/ 09 мая 2018

У меня есть этот интерфейс:

interface IHandler
{
    Type Type { get; } // returns typeof(T).
}

interface IHandler<in T> : IHandler
    where T : IEvent
{
    void Invoke(T ev);
}

Тогда у меня есть функция, которая должна вызывать все Handler<T>.Invoke(T), которые принимают ev.GetType() (это то, что делает GetHandlersFor(Type)). Однако я не могу понять, как вызвать метод Invoke:

    public void Invoke(IEvent ev)
    {
        ImmutableArray<IHandler> selected;
        lock (_listeners)
        {
            selected = GetHandlersFor(ev.GetType()).ToImmutableArray();
        }

        // first attempt
        foreach (var tl in selected)
        {
            Debug.Assert(tl.Type.IsInstanceOfType(ev)); // my data structure invariant
            ((IHandler<IEvent>) tl).Invoke(ev); // InvalidCastException
        }

        // second attempt
        foreach (dynamic tl in selected)
        {
            tl.Invoke(ev); // RuntimeBinderException
        }
    }

В первой попытке я получаю System.InvalidCastException: 'Unable to cast object of type 'MyHandler`1[ChatEvent]' to type 'IHandler`1[IEvent]'.'

Во второй попытке я получаю Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''object' does not contain a definition for 'Invoke''..

Мой отладчик показывает, что тип tl равен MyHandler<ChatEvent>, а тип ev равен ChatEvent. Если вам интересно, MyHandler определяется как class MyHandler<T> : IHandler<T> where T : IEvent { ... }.

Как мне вызвать мои обработчики?

...