开发者

Upcasting without any added data fields

开发者 https://www.devze.com 2022-12-22 20:32 出处:网络
In my project I have a generic Packet class. I would like to be able to upcast to other classes (like LoginPacket or MovePacket).

In my project I have a generic Packet class. I would like to be able to upcast to other classes (like LoginPacket or MovePacket).

The base class contains a command and arguments (greatly simplified):

public class Packet
{
    public String Command;
    public String[] Arguments;
}

I would like to have be able to convert from Packet to LoginPacket (or any other) based on a check if Packet.Command == "LOGIN". The login packet would not contain any new data members, but only methods for accessing specific arguments. For example:

public class LoginPacket : Packet
{
    public String Username
    {
        get { return Arguments[0]; }
        set { Arguments[0] == value; }
    }
    public String Password
    {
        get { return Arguments[1]; }
        set { Arguments[1] == value; }
    }
}

It would be great if I could run a simple code that would cast from Packet to LoginPacket with something like LoginPacket _Login = (LoginPacket)_Packet;, but that throws a System.InvalidCastException.

It seems like this would be an easy task, as no new data is included, but I can't figure out any other way than copying everything from the Packet cla开发者_C百科ss to a new LoginPacket class.


A better approach is to make Packet instance encapsulated by LoginPacket.

This will allow you to do:

LoginPacket _Login = new LoginPacket(_packet);

Also consider creating a PacketFactory where all the logic needed to create various Packet's goes in.

public class Packet
{
    public String Command;
    public String[] Arguments;
}

public abstract class AbstractPacket
{
    private Packet _packet;

    public AbstractPacket(Packet packet)
    {
        _packet = packet;
    }

    public string this[int index]
    {
        get { return _packet.Arguments[index]; }
        set { _packet.Arguments[index] = value; }
    }
}

public class LoginPacket : AbstractPacket
{
    public LoginPacket(Packet packet): base(packet)
    {            
    }

    public string Username
    {
        get { return base[0]; }
        set { base[0] = value; }
    }
    public string Password
    {
        get { return base[1]; }
        set { base[1] = value; }
    }

}


If different type of Packets differ only by available data members then you could do something below:

Use PacketGenerator to generate packets as:

Packet packet = PacketGenerator.GetInstance(packetdata);

Access the properties as:

Console.WriteLine("User Name: {0}", packet["UserName"]);

Code..

public enum PacketType { Undefined, LoginPacket, MovePacket }

public class PacketData
{
    public String Command;
    public String[] Arguments;
}

public class Packet
{
    public readonly PacketType TypeOfPacket;
    private Dictionary<string, string> _argumentMap;

    public Packet(PacketType _packetType,
                  Dictionary<string, string> argumentMap)
    {
        TypeOfPacket = _packetType;
        _argumentMap = argumentMap;
    }

    public string this[string index]
    {
        get { return _argumentMap[index]; }
        set { _argumentMap[index] = value; }
    }
}

public static class PacketFactory
{
    Packet GetInstance(PacketData packetData)
    {
        Dictionary<string, string> argumentMap
                            = new Dictionary<string, string>();
        PacketType typeOfPacket = PacketType.Undefined;

        // Replace inline strings/int with static/int string definitions
        switch (packetData.Command.ToUpper())
        {
            case "LOGIN":
                typeOfPacket = PacketType.LoginPacket;

                argumentMap["UserName"] = packetData.Arguments[0];
                argumentMap["PassWord"] = packetData.Arguments[1];
                break;

            case "MOVE":
                typeOfPacket = PacketType.MovePacket;
                //..
                break;
            default:
                throw new ArgumentException("Not a valid packet type");
        }

        return new Packet(typeOfPacket, argumentMap);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消