Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用泛型和继承进行类型转换_C#_Generics_Casting - Fatal编程技术网

C# 使用泛型和继承进行类型转换

C# 使用泛型和继承进行类型转换,c#,generics,casting,C#,Generics,Casting,我向您介绍了这个问题,这个问题来自NullReferenceException,这是因为当我通过返回null的As运算符将DofusClient对象转换为TClient时(错误的强制转换原因)。我不明白为什么编译器拒绝我这个强制转换,而TClient在调用我的类时是继承了DofusClient的类型为AuthClient的对象,然后我在类框架管理器的where子句中添加了它 public class FrameManager<TClient> : IFrameManager wher

我向您介绍了这个问题,这个问题来自
NullReferenceException
,这是因为当我通过返回null的As运算符将DofusClient对象转换为TClient时(错误的强制转换原因)。我不明白为什么编译器拒绝我这个强制转换,而TClient在调用我的类时是继承了
DofusClient
的类型为
AuthClient
的对象,然后我在类框架管理器的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, Action<TClient, 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, "NETWORK-FRAME", $"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, Action<TClient, IDofusMessage>>.Builder m_frames;

       public FrameBuilder()
       { this.m_frames = ImmutableDictionary.CreateBuilder<int, Action<TClient, 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, Action<TClient, 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, 0, new WrappedBool(false), "lol", 12222, 222, 000222
                , new WrappedBool(false), 0));
        }

    }
公共类FrameManager:IFrameManager其中TClient:DofusClient
{
私有只读不可变字典m_帧;
私有IContextHandler m_线程;
公共框架管理器(不可变字典框架,
IContextHandler(线程)
{
此.m_frames=帧;
此.m_线程=线程;
}
public void Execute(DofusClient-client,TMessage-message),其中TMessage:IDofusMessage
{
if(!m_frames.TryGetValue(message.ProtocolId,out var方法))
Logger.Instance.Log(LogLevel.Warn,“NETWORK-FRAME”,“$”消息id{Message.ProtocolId}存在,但未列在帧上。“);
其他的
{
Logger.Instance.Log(LogLevel.Info,“NETWORK-FRAME”,“Message Id{Message.ProtocolId}已被解析和处理。”);
m_threading.ExecuteInContext(()=>方法(客户端作为TClient,消息));
}
}
}
公共类框架生成器
{
私有只读ImmutableDictionary.Builder m_frames;
公共框架生成器()
{this.m_frames=ImmutableDictionary.CreateBuilder();}
public FrameBuilder RegisterFrame(),其中TFrame:IFrame,new()
{
IFrame frame=新的TFrame();
德尔行动;
MessageHandlerAttribute属性;
IEnumerable方法=frame.GetType()
.GetMethods()
.Where(x=>(x.GetCustomAttribute(typeof(MessageHandlerAttribute))
as messagehandleAttribute)!=null);
foreach(方法中的MethodInfo方法)
{
attribute=(MessageHandlerAttribute)方法.GetCustomAttribute(typeof(MessageHandlerAttribute));
del=Delegate.CreateDelegate(typeof(Action),null,method)
作为行动;
m_frames.Add(attribute.MessageId,del);
}
Logger.Instance.Log(LogLevel.Debug,$“FRAME-BUILDER”,
$“{methods.Count()}从{typeof(TFrame.Name}处理的方法”;
归还这个;
}
公共ImmutableDictionary Build()
{返回m_frames.ToImmutable();}
}
公共类框架调度器
{
私有只读不可变字典m_messageProvider;
私有只读IFrameManager m_frameManager;
公共FrameDispatcher(ImmutableDictionary消息提供程序、IFrameManager frameManager)
{
this.m_messageProvider=messageProvider;
this.m_frameManager=frameManager;
}
公共void调度(DofusClient客户端,框架)
{
int key=frame.Metadata.MessageId;
if(!m_messageProvider.TryGetValue(key,out var msgCtor))
Logger.Instance.Log(LogLevel.Warn,“[NETWORK]”,$“收到的消息不在协议中:{key}”);
其他的
{
IDofusMessage message=msgCtor();
var reader=新的DofusReader(frame.Payload);
消息。反序列化(读卡器);
m_frameManager.Execute(客户端,消息);
}
}
公共类标识框架:IFrame
{
[MessageHandler(IdentificationMessage.NetworkId)]
public void HandleIdentificationMessage(AuthClient客户端,IDofusMessage消息)
{
var message=msg作为IdentificationMessage;
/*这里AuthClient为null*/
_=client.SendMessageAsync(新标识SuccessMessage()
.InitIdentificationSuccessMessage(“测试”,“空”,1,0,新包装工具(假),“lol”,122222,222,000222
,新WrappedBool(false),0);
}
}
当然,直接将类型AuthClient放在Frame Builder.cs和Frame Manager.cs中会更容易,但是项目被分成几个程序集,其中AuthClient不在其他类的程序集中。此外,FrameBuilder/FrameManager将被重用为另一种类型的数据,因此我不希望在代码中重复我自己。


感谢阅读并祝您度过愉快的一天。

注意事项:根据您的情况使用正确的强制转换运算符将使您的代码更易于调试。
as
运算符在无法进行强制转换时返回
null
,这意味着很难知道这是一个错误的强制转换,或者该值最初是
null
。a除非您有充分的理由将
用作
客户端
在传递给
Execute
之前很可能是空的。因为我们看不到它是在哪里创建的,请按上述方式修复您的强制转换,错误应该会变得更清楚。感谢您的回复。但是,当客户端传递给t时,它不是空的他在调试时执行方法,我在debugger视图中看到实例。好-那么调试时
TClient
的类型是什么?TClient是
DofusClient
的不同子类型吗?TClient是AuthClient对象,AuthClient是DofusClient的子类型,但
TClient childClient=client作为TClient;
返回null。可能是因为FrameManager和AuthClient不在同一个项目(程序集)中?我真的不知道。。