Причина тому неоднозначность между Endpoint<TReq> и Endpoint<TRes>, поскольку нет возможности определить означает типовой параметр запрос или ответ.
А могли бы определить один единственный тип Endpoint<TReq, TRes> и подставлять на место позиционных параметров фиктивный тип Unit тогда, когда запроса или ответа не ожидается.
Подобный подход использует MediatR, например, как правильно выше заметили, с его IRequestHandler.
Hidden text
P.S. в функциональщине unit-типы вообще куда натуральнее смотрятся чем отсутствие типа или void. Посмотрите как изящно в том же F# там сделаны нативные делегаты. Вместо 100500 типов а-ля
А могли бы определить один единственный тип
Endpoint<TReq, TRes>
и подставлять на место позиционных параметров фиктивный тип Unit тогда, когда запроса или ответа не ожидается.Подобный подход использует MediatR, например, как правильно выше заметили, с его IRequestHandler.
Hidden text
P.S. в функциональщине unit-типы вообще куда натуральнее смотрятся чем отсутствие типа или void. Посмотрите как изящно в том же F# там сделаны нативные делегаты. Вместо 100500 типов а-ля
Action, Action<T1>, ..Action<T1, ..T7>, Func<R>, ..Func<T1,..T7, R>
там один единственный
FSharpFunc<T, R>
и прекрасно
причём работает.