매번 아래와 같은 코드를 직접작성하는 것은 실수를 유발할 수 있다
자동화를 해보자
class PlayerInfoReq : Packet
{
public long playerId;
public string name;
public struct SkillInfo
{
public int id;
public short level;
public float duration;
public bool Write(Span<byte> s, ref ushort count)
{
bool success = true;
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), id);
count += sizeof(int);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), level);
count += sizeof(short);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), duration);
count += sizeof(float);
return success;
}
public void Read(ReadOnlySpan<byte> s, ref ushort count)
{
id = BitConverter.ToInt32(s.Slice(count, s.Length - count));
count += sizeof(int);
level = BitConverter.ToInt16(s.Slice(count, s.Length - count));
count += sizeof(short);
duration = BitConverter.ToSingle(s.Slice(count, s.Length - count));
count += sizeof(float);
}
}
패킷을 XML을 통해 정의하자
<?xml version="1.0" encoding="utf-8" ?>
<PDL>
<packet name="PlayerInfoReq">
<long name="playerId"/>
<string name="name"/>
<list name="skill">
<int name="id"/>
<short name="level"/>
<float name="duration"/>
</list>
</packet>
</PDL>
XML이 위와 같이 정의되어 있으면 이를 파싱하는 PacketGenerator를 구현해 보자
namespace PacketGenerator
{
class Program
{
static void Main(string[] args)
{
XmlReaderSettings settings = new XmlReaderSettings()
{
IgnoreComments = true,
IgnoreWhitespace = true
};
// (참고) PDL.xml파일이 exe와 같은 경로에 있어야함.
using (XmlReader r = XmlReader.Create("PDL.xml", settings))
{
// using을 사용할경우 알아서 Dispose(delete)를 호출해 준다
r.MoveToContent();
while(r.Read())
{
Console.WriteLine(r.Name + " " + r["name"]);
}
}
}
}
}
간단하게 이름정도 읽어온다
템플릿에 자동화된 코드가 들어간다(자세한건 코드 참조)