简体   繁体   English

如何创建从实现接口的基类派生的实例列表?

[英]How to create list of instances deriving from a base class that implements interface?

Consider the following interface and class declarations. 考虑以下接口和类声明。

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> { }

Now I want to declare a list of processor instances like so, but cannot figure out what generic type will allow me to add any derived processor type to the list. 现在,我想像这样声明处理器实例的列表,但无法弄清楚哪种通用类型将允许我将任何派生的处理器类型添加到列表中。

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

I have tried: 我努力了:

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

and

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

and

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

What should the type of this list be? 此列表的类型应该是什么? I know I must be missing something obvious here. 我知道我一定会在这里遗漏一些明显的东西。 Any help here would be greatly appreciated. 在这里的任何帮助将不胜感激。 Thanks! 谢谢!

You need to introduce IMessageProcessor and inherit all your Processors from it. 您需要引入IMessageProcessor并从中继承所有处理器。 In list you would have to use this interface. 在列表中,您将必须使用此界面。

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 {
}

And Processors: 和处理器:

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

Since there is no inheritance relationship between ISomething<Type1> and ISomething<Type2> you can't have list of objects that contain mix of those types. 由于ISomething<Type1>ISomething<Type2>之间没有继承关系,因此无法获得包含这些类型的混合对象的列表。

Only real option is to force some base type - either use List<object> or better have base non-generic interface for IMessageProcessor<T> like IMessageProcessor<T> : IMessageProcessor . 唯一的真实选择是强制某种基本类型-使用List<object>或更好地为IMessageProcessor<T>提供基本的非通用接口,例如IMessageProcessor<T> : IMessageProcessor

Unfortunately it also means you can't have access to properties/arguments using generic type without casts. 不幸的是,这也意味着如果没有强制类型转换,您将无法使用泛型访问属性/参数。

I'm not sure what you are trying to accomplish, but your code will indeed not work. 我不确定您要完成什么,但是您的代码确实无法正常工作。

I did the following: 我做了以下事情:

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

And then: 接着:

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

will work. 将工作。

The problem is that 问题是

public class MessageAProcessor : MessageProcessorBase<MessageA> { }

is too specific, and you can't cast this back to MessageProcessorBase<MessageBase> in the List<> . 太具体了,您不能将其回退到List<>中的MessageProcessorBase<MessageBase> List<>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM