Как стать автором
Обновить

Порядок полей в соответствии с порядком в коде (C#)

Время на прочтение2 мин
Количество просмотров7.9K
При работе с отражением (Reflection) порядок отраженных полей не гарантируется. Обычно это не имеет значения, но иногда нужен порядок в точном соответствии порядку определенному в коде. Например, это бывает необходимо для частичной сериализации.
Для решения этой надуманной проблемы мы воспользуемся сервисами межъязыкового взаимодействия.



Для начала мы пометим класс атрибутом StructLayoutAttribute с параметром LayoutKind.Sequential. Это заставит компилятор расположить поля в неуправляемой памяти в порядке объявленном в коде. После этого мы отсортируем отраженные поля по смещению относительно начала класса с помощью метода Marshal.OffsetOf.

Пример тестового класса:
[StructLayout(LayoutKind.Sequential)]
public class TestClass1
{
    public int Value1;
    public string Value2;
    public bool Value3;
}


Пример сортировки отраженных полей:
      Type type = typeof(TestClass1);
      List<FieldInfo> fields = new List<FieldInfo>(type.GetFields());

      // исходный порядок
      foreach (FieldInfo field in fields)
        Console.WriteLine(field.Name);
      Console.WriteLine();

      // сортируем по типам (сбиваем порядок)
      fields.Sort(
        delegate(FieldInfo _first, FieldInfo _second)
        {
          int first = _first.FieldType.GetHashCode();
          int second = _second.FieldType.GetHashCode();
          return first.CompareTo(second);
        }
      );

      foreach (FieldInfo field in fields)
        Console.WriteLine(field.Name);
      Console.WriteLine();

      // сортируем по размещению в коде
      fields.Sort(
        delegate(FieldInfo _first, FieldInfo _second)
        {
          int first = Marshal.OffsetOf(type, _first.Name).ToInt32();
          int second = Marshal.OffsetOf(type, _second.Name).ToInt32();
          return first.CompareTo(second);
        }
      );

      foreach (FieldInfo field in fields)
        Console.WriteLine(field.Name);
      Console.WriteLine();


В каких же случаях может понадобится такое? Скажу честно, в очень редких. Не рекомендуется писать какой-либо код, зависящий от порядка, но все же бывает когда это может пригодится:
  • Частичная сериализация (обновление конкретного поля через сеть, упорядочивание по имени может иметь побочный эффект при рефакторинге)
  • Маппинг в другие типы
  • Маппинг в другие языки
  • Порядок отображения полей в инструментарии (визуальный порядок будет совпадать с порядком в коде)
Теги:
Хабы:
Всего голосов 12: ↑8 и ↓4+4
Комментарии5

Публикации

Истории

Работа

Ближайшие события

27 августа – 7 октября
Премия digital-кейсов «Проксима»
МоскваОнлайн
28 сентября – 5 октября
О! Хакатон
Онлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
10 – 11 октября
HR IT & Team Lead конференция «Битва за IT-таланты»
МоскваОнлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн