2016-09-21 111 views
2

考虑下面的接口和类声明。如何创建从实现接口的基类派生的实例列表?

public interface IMessage 
{ 
    string Body { get; set; } 
} 
public abstract class MessageBase : IMessage 
{ 
    public string Body { get; set; } 
} 
public class MessageA : MessageBase { } 
public class MessageB : MessageBase { } 
public class MessageC : MessageBase { } 

public interface IMessageProcessor<T> where T : IMessage 
{ 
    Action<T> ProcessorAction { get; set; } 
} 
public abstract class MessageProcessorBase<T> : IMessageProcessor<T> where T : MessageBase 
{ 
    public Action<T> ProcessorAction { get; set; } 
} 
public class MessageAProcessor : MessageProcessorBase<MessageA> { } 
public class MessageBProcessor : MessageProcessorBase<MessageB> { } 
public class MessageCProcessor : MessageProcessorBase<MessageC> { } 

现在我要声明,像这样的处理器实例列表,但无法弄清楚什么泛型类型可以让我的任何派生处理器类型添加到列表中。

var processors = new List<???>(); 
processors.Add(new MessageAProcessor()); 
processors.Add(new MessageBProcessor()); 
processors.Add(new MessageCProcessor()); 

我曾尝试:

// compiles but throws InvalidCastException 
var processors = new List<IMessageProcessor<IMessage>>(); 
processors.Add((IMessageProcessor<IMessage>)new MessageAProcessor()); 

// compiles but throws InvalidCastException 
var processors = new List<IMessageProcessor<MessageBase>>(); 
processors.Add((IMessageProcessor<MessageBase>)new MessageAProcessor()); 

// won't compile 
var processors = new List<MessageProcessorBase<MessageBase>>(); 
processors.Add((MessageProcessorBase<MessageBase>)new MessageAProcessor()); 

我应该这个列表的类型是什么?我知道我必须在这里错过一些明显的东西。任何帮助在这里将不胜感激。谢谢!

回答

3

您需要引入IMessageProcessor并继承您的所有处理器。在列表中你将不得不使用这个接口。

public interface IMessage { 
    string Body { get; set; } 
} 

public abstract class MessageBase : IMessage { 
    public string Body { get; set; } 
} 

public class MessageA : MessageBase { 
} 

public class MessageB : MessageBase { 
} 

public class MessageC : MessageBase { 
} 

public interface IMessageProcessor<T> where T : IMessage { 
    Action<T> ProcessorAction { get; set; } 
} 

public abstract class MessageProcessorBase<T> : IMessageProcessor<T> where T : MessageBase { 
    public Action<T> ProcessorAction { get; set; } 

    public void ProcessMessage(IMessage message) { 
     var msg = message as T; 
     ProcessorAction(msg); 
    } 
} 

public interface IMessageProcessor { 
    void ProcessMessage(IMessage message); 
} 

public class MessageAProcessor : MessageProcessorBase<MessageA>,IMessageProcessor { 
} 

public class MessageBProcessor : MessageProcessorBase<MessageB>,IMessageProcessor { 
} 

public class MessageCProcessor : MessageProcessorBase<MessageC>,IMessageProcessor { 
} 

和处理器:

var processors = new List<IMessageProcessor>(); 
processors.Add(new MessageAProcessor()); 
processors.Add(new MessageBProcessor()); 
processors.Add(new MessageCProcessor()); 
+0

您可以将'ProcessMessage'实现移至基址:'var msg = message as T' –

+0

@AlekseyL。好点,修正了,谢谢 – 3615

+0

@ 3615谢谢 - 现在我明白了。 –

1

既然有ISomething<Type1>之间并没有继承关系ISomething<Type2>你不能拥有包含这些类型的组合对象的列表。

唯一真正的选择是迫使一些基本类型 - 无论是使用List<object>或更好的有基非通用接口IMessageProcessor<T>IMessageProcessor<T> : IMessageProcessor

不幸的是,它也意味着你不能使用没有强制转换的泛型类型访问属性/参数。

0

我不确定你想要完成什么,但是你的代码确实不起作用。

我做了以下内容:

public class MessageAProcessor : MessageProcessorBase<MessageBase> { } 
public class MessageBProcessor : MessageProcessorBase<MessageBase> { } 
public class MessageCProcessor : MessageProcessorBase<MessageBase> { } 

然后:

var processors = new List<MessageProcessorBase<MessageBase>>(); 
processors.Add(new MessageAProcessor()); 
processors.Add(new MessageBProcessor()); 
processors.Add(new MessageCProcessor()); 

会工作。

的问题是,

public class MessageAProcessor : MessageProcessorBase<MessageA> { } 

是太具体了,你不能在List<>投这回MessageProcessorBase<MessageBase>

相关问题