Я пытаюсь найти способ определить, будет ли данный тип сериализоваться правильно через 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>
, не проходят оба эти теста.
После просмотра источника и просмотра таких вещей, как knownCodes
(и ProtoTypeCode
в целом), кажется, что самый простой способ добиться того, чего я хочу, - это создать собственную версию такой список и проверить против него. Если тип не существует в этом списке, я бы запустил что-то вроде моего кода выше. Это кажется в основном полным, но не учитывает общие типы коллекций и тому подобное.
Прежде чем я попытаюсь взломать все это вместе, есть ли у кого-нибудь предложение для лучшего, более канонического способа сделать проверку таким образом? Я делаю какие-либо предположения, которые просто ошибочны? Спасибо!