Questo è un caso complicato. Puoi usare co/controvarianza, ma ...
semplificherò un po 'il codice. Giusto per chiudere il compilatore si può fare:
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
farà il trucco come suggerito in un'altra risposta, ma fondamentalmente non risolvere nulla. Mi permetta di mostrare, ora si vuole fare l'interfaccia:
public interface IConsumer<out IMessage>
{
object Process (IMessage m);
}
aaaand non si compila. Perché semplicemente messo se dici out IMessage
significa che i tipi di ritorno dovrebbero essere derivati da IMessage
, non i tipi di parametri.
in modo da avere in questo modo:
public interface IConsumer<in IMessage>
{
object Process (IMessage m);
}
public class Mop1 : IConsumer<Message1>
{
public object Process (Message1 msg)
{
return null;
}
}
Per rendere più compilare e valido. Ma ora il tuo list.Add(mop);
non funzionerà. E giustamente, perché il vostro Mop1
non è infatti calcinabile per IConsumer<IMessage>
perché se stava seguendo il codice sarebbe possibile:
list[0].Process (new Message2());
e non è possibile perché MOP1 solo Message1
accetta.
Quindi per rispondere alla domanda. Non si può davvero fare nulla di significativo con l'invio di messaggi e le caratteristiche del compilatore C#. Vedo dove stava andando, volevi una battitura statica con messaggi e cose. Purtroppo non è possibile avere un elenco di consumatori che consumano messaggi specifici nell'elenco generico, è necessario disporre di firme astratte come bool CanProcess(IMessage); IMessage Process(IMessage);
ed eseguire il cast all'interno. Puoi anche farlo leggermente meglio con gli attributi personalizzati e la riflessione, ma ancora una volta, non solo con il compilatore C#.
È davvero fantastico. –
Tranne che non è esattamente questo, anche se compila.Il consumatore prende i messaggi, quindi dovrebbe essere "in" ma non verrà compilato. La logica originale è rotta. – Andrey
@Andrey Dovremmo esaminare alcune firme dei metodi per capire cosa dovrebbe essere dentro e fuori. In questo momento le interfacce sono completamente vuote. –