【问题标题】:How to create list of instances deriving from a base class that implements interface?如何创建从实现接口的基类派生的实例列表?
【发布时间】:2016-09-21 07:06:07
【问题描述】:

考虑以下接口和类声明。

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());

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

【问题讨论】:

    标签: c# generics inheritance interface


    【解决方案1】:

    您需要引入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());
    

    【讨论】:

    • 您可以将ProcessMessage 实现移动到基础:var msg = message as T
    • @3615 谢谢 - 现在我明白了。
    【解决方案2】:

    由于ISomething&lt;Type1&gt;ISomething&lt;Type2&gt; 之间没有继承关系,因此您不能拥有包含这些类型混合的对象列表。

    唯一真正的选择是强制使用某些基本类型 - 要么使用 List&lt;object&gt;,要么更好地使用 IMessageProcessor&lt;T&gt; 的基本非泛型接口,例如 IMessageProcessor&lt;T&gt; : IMessageProcessor

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

    【讨论】:

      【解决方案3】:

      我不确定您要完成什么,但您的代码确实无法正常工作。

      我做了以下事情:

      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&lt;&gt; 中把它转换回MessageProcessorBase&lt;MessageBase&gt;

      【讨论】:

        猜你喜欢
        • 2014-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-17
        • 2011-11-05
        • 1970-01-01
        • 2010-09-22
        相关资源
        最近更新 更多