Это сложный случай. Вы можете использовать co/contravariance, но ...
Я немного упрощу код. Просто заткнись компилятор вы можете сделать это:
public interface IMessage { }
public interface Message1 : IMessage { }
public class Mop1 : IConsumer<Message1>
{
}
public interface IConsumer<out IMessage>
{
}
class Program
{
static void Main(string[] args)
{
var list = new List<IConsumer<IMessage>>();
var mop = new Mop1();
list.Add(mop); // Error occurs here
}
}
out IMessage
будет делать трюк, как это предлагается в другой ответ, но принципиально ничего не исправить. Позвольте мне показать, теперь вы хотите сделать свой интерфейс:
public interface IConsumer<out IMessage>
{
object Process (IMessage m);
}
aaaand не компилируется. Потому что просто положите, если вы скажете out IMessage
, это означает, что типы возврата должны быть получены из IMessage
, а не типов параметров.
Таким образом, вы будете иметь это так:
public interface IConsumer<in IMessage>
{
object Process (IMessage m);
}
public class Mop1 : IConsumer<Message1>
{
public object Process (Message1 msg)
{
return null;
}
}
Чтобы сделать его скомпилировать и действительным. Но теперь ваш list.Add(mop);
не будет работать. И это справедливо, потому что ваш Mop1
действительно не преобразуемый IConsumer<IMessage>
, потому что если он был следующим код будет возможен:
list[0].Process (new Message2());
и это не представляется возможным, потому что СС1 принимает только Message1
.
Чтобы ответить на вопрос. Вы не можете реально сделать что-либо значимое с отправкой сообщений и чистыми функциями компилятора C#. Я вижу, где это происходит, вы хотели, чтобы статическая типизация с сообщениями и прочее. К сожалению, у вас не может быть списка потребителей, которые потребляют определенные сообщения в общем списке, у вас должны быть абстрактные сигнатуры, такие как bool CanProcess(IMessage); IMessage Process(IMessage);
и литые внутрь. Вы также можете сделать это немного лучше с пользовательскими атрибутами и отражением, но опять же, а не только с C# компилятором.
Это довольно круто. –
За исключением того, что это не совсем то, хотя компилируется.Потребитель принимает сообщения, поэтому он должен быть 'in', но тогда он не будет компилироваться. Исходная логика нарушена. – Andrey
@ Andrey Нам нужно посмотреть на некоторые подписи методов, чтобы выяснить, что должно быть и должно быть. В настоящее время интерфейсы полностью пусты. –