Сериализация неуправляемого универсального типа в C # 7.3 - PullRequest
0 голосов
/ 18 мая 2018

Неуправляемое ключевое слово , добавленное в C # 7.3 , предназначено в основном для взаимодействия.Но также сказал , что это может облегчить общие методы сериализации.Точно так же этот ответ показывает часть того, как это можно сделать - в частности, десериализовать массив неуправляемых элементов.

Мне интересно, безопасно ли это делать.Есть как минимум две проблемы.Во-первых, исходя из моих экспериментов, мне кажется, что оператор sizeof (T) все еще должен использоваться в небезопасном контексте, даже там, где применяется неуправляемое ограничение T :.Кажется, это согласуется с предположением, что даже при неуправляемом ограничении разные платформы могут по-разному планировать неуправляемые структуры (если, например, не используется LayoutKind.Sequential), поэтому sizeof ненадежен для целей сериализации, , как это было раньше.И, конечно же, мы должны использовать небезопасный контекст, чтобы получить байты, лежащие в основе универсального T.

Во-вторых, числовые типы также могут иметь разные макеты на разных платформах.Таким образом, код Microsoft, использующий Span, включает методы, которые будут специально читать / писать с указанным порядком байтов, например здесь .Если сериализовать неуправляемый T на одной платформе и десериализовать на другой, то может показаться, что существует риск, что мы получим обратно числа с другим порядком байтов.

Таким образом, мой вывод заключается в том, что простое сериализация лежащих в основе байтов T небезопасно, если только у кого-то нет уверенности в том, что десериализация будет происходить на той же платформе.Это правильно?

Предполагая, что это так, связанный с этим вопрос заключается в том, как мы все еще можем сериализовать неуправляемый T в общем.Предположительно, мы могли бы использовать отражение на T, чтобы выяснить, какие типы используются, и затем мы можем определить расположение T , используя небезопасный код .Затем, принимая во внимание, является ли текущая система прямым или прямым порядком байтов, должна быть возможность разработать алгоритм, который будет сериализовать и десериализовать общий неуправляемый T. Это правильно?(Конечно, если бы кто-то сделал это, это было бы идеально.)

1 Ответ

0 голосов
/ 11 июля 2019

Это сообщение в блоге и связанный код иллюстрируют, как сериализовать и десериализовать структуры, которые объявлены неуправляемыми.Один из подходов к сериализации заключается в следующем:

public static void Write<T>(this Stream stream, T value)
    where T : unmanaged
{
    var tSpan = MemoryMarshal.CreateSpan(ref value, 1);
    var span = MemoryMarshal.AsBytes(tSpan);
    stream.Write(span);
}

Соответствующий код десериализации:

public static T Read<T>(this Stream stream)
    where T : unmanaged
{
    var result = default(T);
    var tSpan = MemoryMarshal.CreateSpan(ref result, 1);
    var span = MemoryMarshal.AsBytes(tSpan);
    stream.Read(span);
    return result;
}

Как и ожидалось, это приводит к значительному увеличению скорости, задокументированному в сообщении в блоге.Таким образом, это может быть полезным методом сериализации, когда данные хранятся в виде диапазона неуправляемого типа.Однако этот метод предполагает, что значения десериализуются на платформе с тем же порядком байтов, что и платформа, на которой они были сериализованы.Для некоторых приложений это вряд ли будет проблемой, учитывая преобладание машин с прямым порядком байтов.Если это проблема, можно проверить машину с прямым порядком байтов и затем преобразовать значения перед сериализацией и после десериализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...