2016-09-21 145 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>