Я пытаюсь использовать различающееся объединение для представления некоторых пользовательских типов; однако типы, которые составляют случаи DU, содержат пользовательские атрибуты, которые не соблюдаются DU. Например, я выполняю маршалинг заголовка файла, который содержит несколько необязательных полей в расширении заголовка, в зависимости от программы, написавшей файл. Поля структуры также имеют собственный атрибут, который позволяет маршалировать поля структуры с правильным порядком байтов, заданным [<endian>]
. Учитывая общую базовую структуру заголовка,
[<Struct; StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)>]
type generic_header = {
[<endian>] header_size: int16
[<MarshalAs(UnmanagedType.ByValTStr, SizeConst = 55)>]
file_version: string
[<endian>] file_size: int16
header_extension: bool
}
и расширение заголовка с полями +/- в зависимости от программы, с помощью которой был создан заголовок,
[<Struct; StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)>]
type header_extension = {
[<endian>] extended_field_1: int16
[<endian>] extended_field_2: float32
[<MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)>]
extended_array: byte[]
[<endian>] extended_field_3: int16
...
}
возможно ли иметь распознаваемое объединение (или даже другую структуру), которое может содержать эти типы, и использовать тип DU для объединения потока в содержащиеся структуры? Если я марширую каждый тип отдельно, тогда атрибут endian будет соблюдаться, и я получу правильные данные.
Что я пробовал до сих пор:
[<Struct>]
type file_header =
| Header of Header: generic_header
| Extension of Extension: header_extension
или
[<Struct>] type file_header = | Header of generic_header * header_extension
или некоторая логика регистра для выполнения одного из следующих действий на основе значения первого поля generic_header:
[<Struct>] type file_header_from_prog_1 = | Header of generic_header * prog_1_header_extension
[<Struct>] type file_header_from_prog_2 = | Header of generic_header * prog_2_header_extension
[<Struct>] type file_header_from_prog_3 = | Header of generic_header * prog_3_header_extension
Однако, когда я использую тип file_header для маршалинга, он правильно маршалирует правильное число байтов в структуре, но это происходит без учета тега endian на полях.
Моя цель - создать «супертип», который будет содержать все возможные расширения и типы, которые могут составлять заголовок файла, который я маршалирую, чтобы мне не приходилось маршалировать каждый тип по отдельности. Есть ли способ сделать это?