Home > front end >  Access error even though there is a method inside the C# Interface class
Access error even though there is a method inside the C# Interface class

Time:12-27

using Network.Codecs;

namespace Network.Packets 
{

   public interface Packet {
       public void Read(DataSerializer data);
       public void Write(DataSerializer data);
   }

}
using System.Collections.Generic;
using DotNetty.Buffers;
using DotNetty.Codecs;
using DotNetty.Transport.Channels;
using Network.Packets;
using Network.Protocols;

namespace Network.Codecs
{

    public class PacketCodec<Packet> : ByteToMessageCodec<Packet>
    {

        public static DataSerializer CreateDataSerializer(IByteBuffer buf) => new DataSerializer(buf);

        private Client client;

        public PacketCodec(Client client)
        {
            this.client = client;
        }

        protected override void Encode(IChannelHandlerContext context, Packet packet, IByteBuffer output){
            int? id = ProtocolRegistry.GetPacketID(this.client.connection.GetProtocol().GetState(), packet.GetType(), false);
            if (id == null || id < 0){
                throw new System.IO.IOException("Unknown packet ("   packet.GetType().Name   ")");
            }
            else
            {
                DataSerializer serializer = CreateDataSerializer(output);
                serializer.WriteVarInt(id.Value); <<< Getting error here
                packet.Write(serializer);
            }
        }

        protected override void Decode(IChannelHandlerContext context, IByteBuffer input, List<object> output){

        }

    }

}

I am getting this error even though there is a Write method in the 'Packet' interface class.

Error: error CS1061: 'Packet' does not contain a definition for 'Write' and no accessible extension method 'Write' accepting a first argument of type 'Packet' could be found (are you missing a using directive or an assembly reference?)

CodePudding user response:

Packet in your PacketCodec class is totally unrelated to your Packet type. It is generic - that's why we typically use T to avoid confusion.

If you want it to really be class Packet, you should write

public interface IPacket
{
    public void Read(DataContractSerializer data);
    public void Write(DataContractSerializer data);
}

public class ByteToMessageCodec<T> {}

public class PacketCodec<T>  : ByteToMessageCodec<T> where T : IPacket
{
    private readonly DataContractSerializer _data;
    private T _packet;

    public PacketCodec(DataContractSerializer data, T packet)
    {
        _data = data;
        _packet = packet;
    }

    public void Input()
    {
        _packet.Read(_data);
    }

    public void Output()
    {
        _packet.Write(_data);
    }
}

CodePudding user response:

According to the .NET naming conventions interface names must be prepended with an upper case I. Also interface members are public by default.

public interface IPacket
{
    void Read(DataContractSerializer data);
    void Write(DataContractSerializer data);
}

Since PacketCodec will always handle packets of type IPacket, it does not need to be generic.

// Note: only ByteToMessageCodec has a generic type parameter.
public class PacketCodec : ByteToMessageCodec<IPacket>
{
    public static DataSerializer CreateDataSerializer(IByteBuffer buf) =>
        new DataSerializer(buf);

    private Client client;

    public PacketCodec(Client client)
    {
        this.client = client;
    }

    // >>> Here the packet parameter is typed IPacket.
    protected override void Encode(IChannelHandlerContext context, IPacket packet,
        IByteBuffer output)
    {
        int? id = ProtocolRegistry.GetPacketID(
            this.client.connection.GetProtocol().GetState(), packet.GetType(), false);
        if (id == null || id < 0){
            throw new System.IO.IOException("Unknown packet ("   packet.GetType().Name   ")");
        }
        else
        {
            DataSerializer serializer = CreateDataSerializer(output);
            serializer.WriteVarInt(id.Value);
            packet.Write(serializer); // <<< Error was here.
        }
    }

    protected override void Decode(IChannelHandlerContext context, IByteBuffer input,
        List<object> output)
    {
    }
}
  •  Tags:  
  • c#
  • Related