无法从抽象<通用>转换为具体:抽象<具体:通用>

本文关键字:通用 抽象 具体 转换 | 更新日期: 2023-09-27 18:37:24

假设我有以下接口:

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: 无法从"RRMessageProcessor" 转换为 'AMessageProcessor'

似乎转换应该有效...为什么它不能转换?我怎样才能让它工作?

无法从抽象<通用>转换为具体:抽象<具体:通用>

我在另一个答案(已删除)中遇到了关于参数协变类型的问题,但这样的方法可能会解决您的问题:

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

此解决方案允许您使用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

这不是最干净/最漂亮的方法,但它似乎有效。以下是我在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
        }
    }

在泛型类型上,需要将类型定义为协变。请参阅 https://msdn.microsoft.com/en-us/library/dd997386.aspx

这应该有效

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

您可以通过重新定义轻松解决问题

public readonly List<AMessageProcessor<BaseMessage>> AvailableMessageProcessors;

public readonly List<RRMessageProcessor> AvailableMessageProcessors;

因此,您没有转换问题,并且使用的是自定义对象

希望对您有所帮助!