无法从Abstract <generic>转换为Concrete:Abstract <concrete:generic>

时间:2016-03-03 16:31:34

标签: c# generics

假设我有以下界面:

public interface IMessageProcessor<T> where T: BaseMessage {
        void Process(T msg);
    }

我有一个实现此接口的抽象类:

 public abstract class AMessageProcessor<T> : IMessageProcessor<T> where T : BaseMessage {

        protected Controller Controller { get; private set; }

        public AMessageProcessor(Controller controller) {
            Controller = controller;
        }

        public abstract void Process(T msg);
    }

然后我有一条消息:

 public class RRMessage : BaseMessage {
  ...
 }

然后我有一个实现:

public class RRMessageProcessor : AMessageProcessor<RRMessage> {
      public RRMessageProcessor(Controller controller) : base(controller) {}

      public override void Process(RRMessage msg) {

            //do something here
        }
    }

现在在另一个类中,我想为不同的消息列出这些处理器:

 public readonly List<AMessageProcessor<BaseMessage>> AvailableMessageProcessors;

        public MessageProcessingStrategy(Controller controller) {
            AvailableMessageProcessors = new List<AMessageProcessor<BaseMessage>>();

            /* ----- ERROR HAPPENS AT THIS LINE ------ */
            AvailableMessageProcessors.Add(new RRMessageProcessor(controller));

        }

我收到了这个错误:

  

错误CS1503参数1:无法转换为&#39; RRMessageProcessor&#39;至   &#39;&AMessageProcessor LT; BaseMessage&GT;&#39;

似乎转换应该有效...为什么它无法转换?我怎样才能让它发挥作用?

4 个答案:

答案 0 :(得分:1)

我的其他答案(删除)中有关于参数协变类型的问题,但这样的方法可以解决您的问题:

  1. 定义BaseMessageProcessor类(可能是AMessageProcessor),如下所示:

    public abstract class BaseMessageProcessor
    {
        protected Controller Controller { get; private set; }
    
        public BaseMessageProcessor(Controller controller)
        {
            Controller = controller;
        }
    
        public void Process<T>(T msg) where T : BaseMessage
        {
            if (this is IMessageProcessor<T>)
                (this as IMessageProcessor<T>).Process(msg);
    
            throw new NotSupportedException();
        }
    }
    
  2. 定义接口IMessageProcessorOf<T>

    public interface IMessageProcessor<T> where T : BaseMessage
    {
        void Process(T msg);
    }
    
  3. 定义继承BaseMessageProcessor并实现(明确)IMessageProcessorOf<T>的具体处理器:

    public class RRMessageProcessor : BaseMessageProcessor, IMessageProcessorOf<RRMessage>
    {
        public RRMessageProcessor(Controller controller) : base(controller) { }
    
        void IMessageProcessor<RRMessage>.Process(RRMessage msg)
        {
            ...
        }
    }
    
  4. 此解决方案允许您使用AvailableMessageProcessors

    public List<BaseMessageProcessor> AvailableMessageProcessors;
    
    ...
    
    AvailableMessageProcessors = new List<BaseMessageProcessor>();
    AvailableMessageProcessors.Add(new RRMessageProcessor(controller));
    

    因此,如果您有2种邮件类型,例如RRMessageSSMessage,则可以定义一个MultiMessageProcessor

    public class MultiMessageProcessor : BaseMessageProcessor, IMessageProcessorOf<RRMessage>, IMessageProcessorOf<SSMessage>
    {
        public MultiMessageProcessor(Controller controller) : base(controller) { }
    
        void IMessageProcessorOf<RRMessage>.Process(RRMessage msg)
        {
            ...
        }
    
        void IMessageProcessorOf<SSMessage>.Process(SSMessage msg)
        {
            ...
        }
    }
    

    Process()方法的调用将通过BaseMessageProcessor.Process<>

    进行
    multiProcessor.Process(new RRMessage());
    multiProcessor.Process(new SSMessage());
    

    或者只使用RRMessageProcessor并使用与之前相同的想法定义SSMessageProcessor

答案 1 :(得分:0)

这不是最干净/最漂亮的方式,但似乎有效。这是我在 AMessageProcessor 中更改的内容:

public abstract class AMessageProcessor : IMessageProcessor<BaseMessage>

        protected Controller Controller { get; private set; }

        public AMessageProcessor(Controller controller) {
            Controller = controller;
        }

        /* ----- REALLY DON'T WANT TO OVERRIDE THIS METHOD EVERYWHERE --- */
        public abstract void Process(BaseMessage msg);
    }

然后将 RRMessageProcessor 更改为:

public class RRMessageProcessor : AMessageProcessor, IMessageProcessor<RRMessage> {
      public RRMessageProcessor(Controller controller) : base(controller) {}

      /* ----- REALLY DON'T WANT TO OVERRIDE THIS METHOD LIKE THIS EVERYWHERE --- */
      public override void Process(BaseMessage msg) {
            Process(msg as RRMessage);
        }

      public void Process(RRMessage msg) {

            //do something here
        }
    }

答案 2 :(得分:0)

在您的通用类型上,您需要将类型定义为协变。见https://msdn.microsoft.com/en-us/library/dd997386.aspx

这应该有效

public interface IMessageProcessor<in T> where T : BaseMessage
{
    void Process(T msg);
}

答案 3 :(得分:-1)

您可以通过重新定义

轻松解决问题

public readonly List<AMessageProcessor<BaseMessage>> AvailableMessageProcessors;

public readonly List<RRMessageProcessor> AvailableMessageProcessors;

因此,您不会遇到问题并且您正在使用自定义对象

希望能帮到你!