Сценарий: я получил необработанные двоичные данные через HTTP и сохранил данные в байтовом массиве.У меня есть документация, которая описывает различные поля, которые могут представлять двоичные данные, но фактическое значение данных должно быть определено во время выполнения.Например, если байт, представляющий возникновение ошибки = 1, то значение следующего байта изменяется.
Используя C # с .NET 4, я хочу создать один или несколько классов, которые отражают поляописано в документации, а затем каким-то образом инициализировать классы, используя байтовый массив двоичных данных.Мне бы хотелось, чтобы решение минимизировало дублирование кода, а также было модульным и элегантным.
Я рассмотрел создание Serializable классов, но я не понимаю, как это может работать, поскольку я начинаю с байтового массива, которыйне был создан (и, следовательно, не сериализован) мной.
Я также пытался использовать обобщенные элементы и рефлексию для получения размеров и типов полей, содержащихся в пользовательских классах.Затем я использовал эту информацию для динамического выделения данных из байтового массива и назначения их соответствующим полям.Однако этот метод привел к появлению большого количества уродливого, неуправляемого кода.
Будем весьма благодарны за любые советы или указания по разработке расширяемого развязанного решения этой проблемы.
Редактировать:Пример классов, содержащих поля, которые отражают поля в спецификации
public class PriceHistoryResponse : BinaryResponse
{
public List<Quote> quotes { get; set; }
private CountData countData { get; set; }
private EndingDelimiterSection endingDelimiterSection { get; set; }
/* This code performs the logic needed to check for optional fields
and to find the number of times that certain fields are repeated */
public PriceHistoryResponse(byte[] responseBytes) : base(responseBytes)
{
countData = new CountData();
ParseResponseSection(countData);
quotes = new List<Quote>();
for (int i = 0; i < countData.quoteCount; i++)
{
quotes.Add(new Quote());
quotes[i].symbolData = new SymbolData();
ParseResponseSection(quotes[i].symbolData);
if (quotes[i].symbolData.errorCode == 1)
{
quotes[i].errorData = new ErrorData();
ParseResponseSection(quotes[i].errorData);
break;
}
quotes[i].chartBarData = new ChartBarData();
ParseResponseSection(quotes[i].chartBarData);
quotes[i].chartBars = new List<ChartBar>();
for (int j = 0; j < quotes[i].chartBarData.chartBarCount; j++)
{
quotes[i].chartBars.Add(new ChartBar());
ParseResponseSection(quotes[i].chartBars[j]);
}
}
endingDelimiterSection = new EndingDelimiterSection();
ParseResponseSection(endingDelimiterSection);
}
}
class CountData : IResponseSection
{
public int quoteCount { get; set; }
}
public class Quote
{
public SymbolData symbolData { get; set; }
public ErrorData errorData { get; set; }
public ChartBarData chartBarData { get; set; }
public List<ChartBar> chartBars { get; set; }
}
public class SymbolData : IResponseSection
{
public string symbol { get; set; }
public byte errorCode { get; set; }
}
public class ErrorData : IResponseSection
{
public string errorText { get; set; }
}
public class ChartBarData : IResponseSection
{
public int chartBarCount { get; set; }
}
public class ChartBar : IResponseSection
{
public float close { get; set; }
public float high { get; set; }
public float low { get; set; }
public float open { get; set; }
public float volume { get; set; }
public long timestamp { get; set; }
}