2014-10-07 3 views
0

그래서이 코드는 잘 작동하지만,보기에는 어렵습니다. 나는이 비트를 쓰는 더 좋은 방법이 있다는 것이 거의 긍정적이다.스위치 이외의 항목을 구성하는 것이 더 나은 방법일까요?

그래서 기본적으로 데이터의 전체 패킷 일 수도 있고 아닐 수도있는 바이트 배열의 데이터가 있습니다. 처음 몇 바이트는 패킷의 제목 인 Int32로 읽혀집니다. 그것은 패킷의 제 열거 형으로 직접 캐스팅됩니다.

그래서 지금은이 같은 내 패킷 설정이 있습니다

class SomePacket : Packet 
{ 
    PacketType type = PacketType.SomePacket; 

    public override Packet ReadPacket(ref buffer) 
    { 
    //Return if the buffer has all the data for this packet. 
    } 
    ... 
} 

을하지만 이것은 본질적으로이 작업을 수행해야 할 날 리드 :

나는 끔찍한 혼란없이이를 수있는 어떤 방법
public abstract Byte[] CreateSendBuffer(); 

    /// <summary> 
    /// Reads and removes from buffer to make a packet. 
    /// </summary> 
    /// <param name="buffer">Buffer used to try to create a packet.</param> 
    /// <returns></returns> 
    public static Packet ReadBuffer(ref List<Byte> buffer) 
    { 
     if (buffer != null) 
     { 
      if (buffer.Count > sizeof(Int32)) 
      { 
       Byte[] backupBuffer = buffer.ToArray(); 
       try 
       { 
        Packet returnPacket = null; 
        Int32 packetType = TakeInt32(ref buffer); 

        switch ((PacketType)packetType) 
        { 
         case (PacketType.VerifyInfo_s): 
          returnPacket = VerifyInfo_s.ReadPacket(ref buffer); 
          break; 

         case (PacketType.Ping_sp): 
          returnPacket = Ping_sp.ReadPacket(ref buffer); 
          break; 

         case (PacketType.GameInfo_p): 
          returnPacket = GameInfo_p.ReadPacket(ref buffer); 
          break; 

         case (PacketType.DayPhase_p): 
          returnPacket = DayPhase_p.ReadPacket(ref buffer); 
          break; 

         case (PacketType.AddPlayer_p): 
          returnPacket = AddPlayer_p.ReadPacket(ref buffer); 
          break; 

         case (PacketType.Player_Visible_p): 
          returnPacket = Player_Visible_p.ReadPacket(ref buffer); 
          break; 

         case (PacketType.Player_Movement_s): 
          returnPacket = Player_Movement_s.ReadPacket(ref buffer); 
          break; 

         case (PacketType.Player_Movement_p): 
          returnPacket = Player_Movement_p.ReadPacket(ref buffer); 
          break; 

         case (PacketType.Player_Health_p): 
          returnPacket = Player_Health_p.ReadPacket(ref buffer); 
          break; 

         default: 
          DebugLogger.GlobalDebug.LogNetworking("Invalid packet header!"); 
          throw new InvalidPacketRead(); 
        } 

        if (TakeByte(ref buffer) == END_PACKET) 
         return returnPacket; 
        else 
         throw new InvalidPacketRead(); 
       } 
       catch (ArgumentOutOfRangeException e) //Not enough data yet to make a full packet. 
       { 
        DebugLogger.GlobalDebug.LogNetworking("Packet not large enough yet." + e.ToString()); 
        buffer = backupBuffer.ToList(); 
        return null; 
       } 
      } 
     } 
     return null; 
    } 

스위치의?

+2

'사전 '이 (가) 정적으로 생성 되었습니까? – Mephy

+2

나는 switch 문을 선호한다. 엄청나게 명확한 일이며, 유지하기 쉽고 디버깅하기 쉬울 것 같습니다. –

답변

2

일단이 레벨로 내려 가면 코드가 지저분 해집니다. 그것은 단지; 그리고 당신은 그것으로 살아가는 법을 배워야합니다.

말했다되고 그건

, 당신은 Dictionary<PacketType, Func<byte[], Packet>>을 정의하고 다음과 같이 그것을 만들 수 :

var parseMethods = new Dictionary<PacketType, Func<byte[], Packet>>(); 
parseMethods.Add(PacketType.VerifyInfo_s, VerifyInfo_s.ReadPacket); 
... 

returnPacket = parseMethods[(PacketType)packetType](buffer); 

은 더 나은 그 정말인가? 어쩌면, 어쩌면 아니지만, 만약 당신이 정말로 switch에 대항하는 것을 가지면 그것으로 갈 수 있습니다.

+0

'ReadPacket'에'ref' 매개 변수가 있다고 생각하면 람다없이 할 수 있습니까? – Mephy

+0

람다 식은 무엇입니까? – alykins

+0

'VerifyInfo_s.ReadPacket'의 델리게이트를 직접 전달하는 것을 의미합니다. 'refse' 키워드로 인해'Dictionary '이 될 것이고,'parseMethods.Add (PacketType.VerifyInfo_s,() => VerifyInfo_s.ReadPacket (ref buffer);')와 같이 쓰고 싶습니다. – Mephy

관련 문제