具有泛型和继承的类型转换

我向您提出问题,该问题来自NullReferenceException,这是由于以下事实:当我通过As运算符将DofusClient对象转换为TClient时,返回给我的结果为null(错误的转换原因)。我看不到为什么编译器在调用TClass时拒绝我在TClient时执行此强制转换,而该继承是AuthClient类型的DofusClient类型的对象,然后将其添加到类Frame Manager的where子句中。

public class FrameManager<TClient> : IFrameManager where TClient : DofusClient
   {
       private readonly ImmutableDictionary<int,action<TClient,IDofusMessage>> m_frames;
       private IContextHandler m_threading;

       public FrameManager(ImmutableDictionary<int,IDofusMessage>> frames,IContextHandler threading)
       {
           this.m_frames = frames;
           this.m_threading = threading;
       }

       public void Execute<TMessage>(DofusClient client,TMessage message) where TMessage : IDofusMessage
       {
           if (!m_frames.TryGetvalue(message.ProtocolId,out var method))
               Logger.Instance.Log(LogLevel.Warn,"NETWORK-FRAME",$"Message id {message.ProtocolId} exists but isn't listed on frames.");
           else
           {
               Logger.Instance.Log(LogLevel.Info,$"Message Id {message.ProtocolId} has been parsed and treated.");

               m_threading.ExecuteInContext(() => method(client as TClient,message));
           }
       }
   }

public class FrameBuilder<TClient>
   {
       private readonly ImmutableDictionary<int,IDofusMessage>>.Builder m_frames;

       public FrameBuilder()
       { this.m_frames = ImmutableDictionary.CreateBuilder<int,IDofusMessage>>(); }


       public FrameBuilder<TClient> RegisterFrame<TFrame>() where TFrame : IFrame,new()
       {
           IFrame frame = new TFrame();
           action<TClient,IDofusMessage> del;
           MessageHandlerAttribute attribute;
           IEnumerable<MethodInfo> methods = frame.GetType()
                                                   .GetMethods()
                                                   .Where(x => (x.getcustomAttribute(typeof(MessageHandlerAttribute))
                                                   as MessageHandlerAttribute) != null);
           foreach (MethodInfo method in methods)
           {
               attribute = (MessageHandlerAttribute)method.getcustomAttribute(typeof(MessageHandlerAttribute));

               del = Delegate.CreateDelegate(typeof(action<TClient,IDofusMessage>),null,method)
                     as action<TClient,IDofusMessage>;

               m_frames.Add(attribute.MessageId,del);

           }

           Logger.Instance.Log(LogLevel.Debug,$"FRAME-BUILDER",$"{ methods.Count()} methods handled from {typeof(TFrame).Name}.");

           return this;
       }

       public ImmutableDictionary<int,IDofusMessage>> Build()
       { return m_frames.ToImmutable(); }
   }


public class FrameDispatcher
   {
       private readonly ImmutableDictionary<int,Func<IDofusMessage>> m_messageProvider;
       private readonly IFrameManager m_frameManager;

       public FrameDispatcher(ImmutableDictionary<int,Func<IDofusMessage>> messageProvider,IFrameManager frameManager)
       {
           this.m_messageProvider = messageProvider;
           this.m_frameManager = frameManager;
       }

       public void Dispatch(DofusClient client,Frame<DofusMetadata> frame)
       {
           int key = frame.Metadata.MessageId;

           if (!m_messageProvider.TryGetvalue(key,out var msgCtor))
               Logger.Instance.Log(LogLevel.Warn,"[NETWORK]",$"The message received isn't in the protocol : {key}.");
           else
           {
               IDofusMessage message = msgCtor();
               var reader = new DofusReader(frame.Payload);

               message.Deserialize(reader);
               m_frameManager.Execute(client,message);
           }

       }

    public class IdentificationFrame : IFrame
    {
        [MessageHandler(Identificationmessage.NetworkId)]
        public void HandleIdentificationmessage(AuthClient client,IDofusMessage msg)
        {
            var message = msg as Identificationmessage;
            /*Here AuthClient is null*/
           _= client.SendMessageAsync(new IdentificationSuccessMessage()
                .InitIdentificationSuccessMessage("test","null",1,new WrappedBool(false),"lol",12222,222,000222,0));
        }

    }

当然,将AuthClient类型直接放置在Frame Builder.cs和Frame Manager.Cs中会更容易,但是该项目被分为几个程序集,而AuthClient不在其他类的程序集中。另外,FrameBuilder / FrameManager将被重用于另一种类型的数据,因此我不想在代码中重复我自己。

感谢阅读,祝您愉快。

yu_yi2009 回答:具有泛型和继承的类型转换

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3125354.html

大家都在问