Сериализация IEnumerable в protobuf-net

У меня есть библиотека довольно тяжелых DTO, которая в настоящее время используется некоторыми службами WCF. Мы пытаемся перенести его в мир protobuf-net с минимальными изменениями. Один конкретный набор элементов вызывает у меня проблемы с сериализацией. Я собираюсь просто их здесь, потому что это немного усложняется, но суть проблемы такова:

public class Key
{
   public string Id {get; set;}
}

public class KeyCollection : IEnumerable<Key>
{
   private readonly List<Key> list;

#region IEnumerable
   // etc...
#endregion
}

public class Item
{
   public long Id { get; set; }
}

public abstract class ContainerBase
{ }

public abstract class ContainerBase<T> : ContainerBase
   where T : Item
{ }

public abstract class ContainerType1Base : ContainerBase<Item>
{
   public KeyCollection Keys { get; set; }
}

public class ContainerType1 : ContainerType1Base
{ }

Я пропустил декораторы, потому что они не проблема, в основном потому, что если я добавлю void Add(Key item) { } к KeyCollectionвсе вроде работает. В противном случае я столкнусь с проблемами при попытке сериализовать экземпляр ContainerType1.

Собственно, меняя подпись KeyCollectionявляется своего рода запретительным, поэтому я пытаюсь следовать этому ответу, чтобы попытаться сделать это программно. В частности, установка itemType и defaultType обнулить "Ключи" ValueMember из ContainerType1, ContainerType1Base и ContainerBase<Item>. Я также установил IgnoreListHandling к true на KeyCollection... что совершенно не работает. Я получаю общее исключение "не удалось десериализовать" на клиенте, которое я могу опубликовать здесь, если это поможет. На стороне сервера я сериализую его, используя Serializer.Serialize(), и я выплюнул Serializer.GetProto<>() а также JSON объекта, и все они, похоже, работают нормально.

Как отключить обработку списков? В связи с этим, есть ли способ включить дополнительную отладку при сериализации, чтобы попытаться получить дополнительную информацию о проблеме?

1 ответ

Решение

По сути, показанный код выглядит нормально. К сожалению, в настоящее время в gRPC есть "функция", которая означает, что он отбрасывает исходное исключение, когда маршаллер (сериализатор) по какой-то причине дает сбой, поэтому gRPC в настоящее время не выявляет фактическую проблему. Я отправил исправление для этого - оно может быть принято или не принято.

А пока я предлагаю вам просто удалить gRPC из уравнения и смоделировать только рабочую нагрузку маршаллера; для этого на сервере: сгенерируйте данные, которые вы пытаетесь отправить, и выполните:

       var ms = new MemoryStream();
Serializer.Serialize(ms, yourDataHere);
var payload = Convert.ToBase64String(ms.ToArray());

и получить значение payload (это просто string). Теперь на клиенте измените это:

       var ms = new MemoryStream(Convert.FromBase64String(thatStringValue));
Serialize.Deserialize<YourTypeHere>(ms);

Я ожидаю, что это вызовет исключение, которое расскажет вам, в чем реальная проблема.


Если изменение gRPC объединяется, ошибка должна быть доступна через:

       catch (RpcException fault)
{
    var originalFault = fault.Status.DebugException;
    // ^^^
}
Другие вопросы по тегам