Был взят за основу код из ответа на SO.
Нужно была доработка класса MessageHandlerAdapter чтобы в качестве базового типа была команда ICommand<IMessage>, но при попытке собрать MessageHandlerAdapter<ICommandHandler<MyMessage>> получаю ошибку, о том что мой тип не подходит под ограничения.
var handler = typeof(MessageAdapter<>).MakeGenericType(typeof(ICommand<>).MakeGenericType(typeof(MyMessage)));
Сами типы:
public interface IMessage { }
public class MyMessage : IMessage {};
public interface ICommand<TMessage> where TMessage : IMessage {};
public class MessageAdapter<TMessageCommand> where TMessageCommand : ICommand<IMessage> { }
Вопрос: почему это происходит и как решить эту проблему? Ведь MyMessage наследует IMessage.
Зачем мне это нужно: Над классом handler будет висеть кастомный аттрибут с параметрами команды. Для варианта как у автора на SO нельзя узнать тип, который скрывается внутри лямбды, пока не вызовешь. Мой полный код.
Проблема в том, что наследование MyMessage от IMessage не делает вашу команду ICommand<MyMessage> наследницей ICommand<IMessage>! В этом можно убедиться вот таким простым кодом:
ICommand<MyMessage> foo = null;
ICommand<IMessage> bar = foo; // Ошибка компиляции
Для того чтобы ICommand<MyMessage> можно было приводить к типу ICommand<IMessage> - нужно сделать интерфейс ICommand<> ковариантынм:
public interface ICommand<out TMessage> where TMessage : IMessage {};
К сожалению, на ковариантные интерфейсы наложены сильные ограничения, и для команды такой вариант скорее всего не подойдет. В таком случае придется делать ваш MessageAdapter знающим не только тип команды, но и тип сообщения:
public class MessageAdapter<TMessage, TCommand>
where TMessage : IMessage
where TCommand : ICommand<TMessage> { }
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости