#c# #performance #reflection #.net-3.5 #properties
#c# #Производительность #отражение #.net-3.5 #свойства
Вопрос:
У меня есть несколько структур c #, которые придают форму структурам в очень большом файле данных. Эти структуры интерпретируют биты в словах данных файла и преобразуют их в первоклассные свойства. Вот пример одного:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TimeF1_MsgDayFmt
{
// Time Data Words
public UInt16 TDW1;
public UInt16 TDW2;
public UInt16 TDW3;
/// <summary>
/// Tens of milliseconds
/// </summary>
public UInt16 Tmn
{
// Bits.Get is just a helper method in a static class
get { return Bits.Get(TDW1, 0, 4); }
set
{
if (value > 9)
throw new ArgumentOutOfRangeException();
TDW1 = Bits.Set(TDW1, value, 0, 4);
}
}
/// Several other properties follow.
Мне нужно сделать две вещи, которые, я думаю, связаны. Во-первых, необходимо иметь возможность проверять весь класс, используя набор правил проверки. Я знаю, что есть несколько способов сделать это; тот, который мне больше всего нравится, — это аннотировать каждое свойство чем-то вроде этого:
[ValidateRange(0,9)]
public UInt16 Tmn
{
get { return Bits.Get(TDW1, 0, 4); }
set
{
/// etc. Will probably no longer throw the ArgumentOutOfRangeException here.
… а затем используйте Validator
класс для чтения всех атрибутов свойства, сверьте каждое значение свойства с аннотированными правилами и верните коллекцию объектов ошибок. Но меня беспокоит, сколько времени займет отражение; эти структуры должны быть чрезвычайно высокопроизводительными.
public List<Error> Validate(TimeF1_MsgDayFmt original)
Второе, что мне нужно сделать, это выполнить аудит изменений свойств; то есть для каждого свойства, которое изменилось по сравнению с его первоначальным значением, мне нужно иметь возможность получить строку с надписью «Свойство foo изменено с bar на baz». Для этого мне нужен способсравните все свойства «до» и «после» struct
и обратите внимание на различия.
public List<string> Compare(TimeF1_MsgDayFmt original, TimeF1_MsgDayFmt new)
В обоих случаях код будет включать перебор всех свойств и проверку каждого из них по отдельности, причем как можно быстрее.
Как бы я подошел к этому?
Комментарии:
1. Является ли генерация кода этих структур табу?
2. @sixlettervariables Не обязательно. Я видел несколько примеров, подобных этому , где генерируется прокси-объект, но я пока не смог разобраться в этом.
3. Конечно, структуры данных не меняются от момента к моменту. Вы настаиваете на том, чтобы вся эта проверка происходила во время выполнения? Если проверка произошла в автономном режиме, вас может гораздо меньше волновать, насколько быстро она выполняется.
4. @IraBaxter: Я не уверен, что вы имеете в виду. Файлы данных очень большие; время проверки одной структуры может быть не особенно значимым, но если их миллионы…
5. @IraBaxter: Должна ли эта программа «проверять» структуры? Почему? Потому что они могут быть недопустимыми в исходном файле данных. Разве у вас нет отдельного инструмента для проверки структур? Это инструмент, который я создаю. Возможно, вы имеете в виду, что у вас есть миллионы экземпляров небольшого числа типов. Да, это то, что я имею в виду. Я добавил немного больше разъяснений к началу своего вопроса.
Ответ №1:
Если проблема заключается в том, соответствуют ли данные, считываемые в структуру, дополнительным ограничениям, вам прежде всего нужно выяснить, как записать такие ограничения. (В вашем примере вы написали [ValidateRange(0,9)] в качестве одного из таких ограничений).
Как только у вас есть средство для записи ограничений, вам, предположительно, нужно прочитать данные в соответствующую структуру, а затем проверить ограничения. (В вашем примере вы предложили идею использования отражения).
Мне кажется, что самый простой способ записать такие ограничения, которые выполняются быстро, — это просто записать их как дополнительный код C #. Для каждого ограничения, которое вы можете себе представить, вы можете добавить метод класса, который проверяет ограничение и возвращает логическое значение. Вы можете добавить стандартное ограничение «CheckIt», которое вычисляет объединение всех отдельных методов ограничения.
Должно быть легко написать ограничения. Я бы ожидал, что компилятор C # встроит другие методы, особенно если они маленькие и не принимают аргументов (кроме подразумеваемого класса). Это должно ускорить их.
Если компилятор C # этого не сделает, переключитесь на C , где вы можете в значительной степени принудительно встроить.
Комментарии:
1. Да, к такому выводу я тоже приближаюсь. Я думаю, что нашел решение проблемы производительности отражения, смотрите Здесь: fasterflect.codeplex.com , это может оказаться полезным. Проблема, с которой я сталкиваюсь, заключается в краткости кода; с протоколированием, сбором результатов проверки и делегатом / событием, необходимым для обновления основного пользовательского интерфейса, каждый метод проверки будет содержать более 6 строк кода. Я надеялся получить больше, чем одну строку кода для каждого ограничения. Я могу добавить метод Assert в свой класс ведения журнала, который принимает a
Func<bool>
, и позволить моему регистратору обрабатывать все это.