Существует ли метод protobuf-net для обнаружения всех поддерживаемых типов? - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь найти способ определить, будет ли данный тип сериализоваться правильно через protobuf-net. В идеале я написал бы функцию, которая возвращает true, если protobuf-net может правильно обрабатывать тип.

Под «правильно» я подразумеваю, что ненулевой экземпляр типа будет сериализован в ненулевое количество байтов. Я понимаю, что сериализация в нулевые байты вполне допустима в protobuf, но я заинтересован в обнаружении случаев, когда не должен действительно сериализоваться в нулевые байты.

Я взглянул на раздел «Поддержка типов» на странице GitHub, этот ответ и просмотрел исходный код (в основном материал, связанный с RuntimeTypeModel). Одна из моих предыдущих попыток найти решение выглядела так:

public bool WillSerialize<T>()
{
    var t = typeof(T);

    // If the RuntimeTypeModel doesn't know about T, it can't serialize
    var canSerialize = Serializer.NonGeneric.CanSerialize(t);
    if( !canSerialize ) return false;

    // If the RuntimeTypeModel has fields for the given type, they
    // will be serialized.
    var hasFields = RuntimeTypeModel.Default[t].GetFields().Any();

    return hasFields;
}

Насколько я могу судить, проблема в том, что CanSerialize возвращает true только для типов в RuntimeTypeModel (я полагаю, что он просто проверяет существование в RTM). Это возвращает false для таких типов, как uint, хотя uint (и другие примитивы) могут быть очень хорошо сериализованы. Также, обычно из-за ошибки разработчика, мы можем «обмануть» RTM, думая, что он может правильно сериализовать тип, сначала вызвав PrepareSerializer<T>.

Если мы ошибочно подготовим тип, у которого нет полей [ProtoMember] (или того, у которого есть [ProtoAttribute]), но CanSerialize вернет true. Это тот случай, когда второй тест предназначен для ловли. Если RTM имеет MetaType с полями, определенными для данного T, то мы можем предположить, что он будет правильно сериализован. Если нет, наша оболочка protobuf-net выдает предупреждающее сообщение. Недостаток в том, что поддерживаемые типы по умолчанию, такие как Dictionary<TKey, TValue>, не проходят оба эти теста.

После просмотра источника и просмотра таких вещей, как knownCodesProtoTypeCode в целом), кажется, что самый простой способ добиться того, чего я хочу, - это создать собственную версию такой список и проверить против него. Если тип не существует в этом списке, я бы запустил что-то вроде моего кода выше. Это кажется в основном полным, но не учитывает общие типы коллекций и тому подобное.

Прежде чем я попытаюсь взломать все это вместе, есть ли у кого-нибудь предложение для лучшего, более канонического способа сделать проверку таким образом? Я делаю какие-либо предположения, которые просто ошибочны? Спасибо!

...