В целях обучения я пишу клиент-серверное приложение на основе сокетов. Я разработал собственный протокол, чтобы гарантировать, что я могу правильно обрабатывать свои пакеты. Осматривая некоторые старые части кода сегодня, я понял, что мой способ создания пакетов данных содержит много избыточного кода.
У меня есть разные типы пакетов, например, ImagePacket, MessagePacket и т. Д. Создание всех типов отличается только незначительными элементами, например, создание заголовка и разделителя одинаково.
Чтобы улучшить это, я придумал такое решение (упрощенное):
abstract class Packet
{
public Packet(object o)
{
MemoryStream memoryStream = new MemoryStream();
AddHeader(ref memoryStream);
AddData(ref memoryStream, obj);
AddDelimiter(ref memoryStream);
_packetBytes = memoryStream.ToArray();
memoryStream.Close();
}
protected abstract void AddData(ref MemoryStream ms, object obj);
Метод AddData реализован как абстрактный метод и переопределен в конкретных классах, тогда как AddHeader и AddDelimiter определены в самом абстрактном классе Packet.
Это прекрасно работает, и у меня не так много дублированного кода, как раньше, но я не доволен
передача объекта в AddData, потому что не ясно, что я не должен давать строку конструктору ImagePacket.
// correct
Packet myMsgPacket = new MessagePacket("hello world");
Packet myImagePacket = new ImagePacket(image);
// wrong, but will be compiled :(
Packet myChaosPacket = new ImagePacket("muaha you're doomed");
Если бы мне пришлось реализовать проверку на корректность передаваемого типа данных, я бы снова получил тонны глупого кода.
Как я могу добиться сокращения дублированного кода, а также избавиться от проблемы, упомянутой выше?