Я пытаюсь перенести существующий код, использующий XmlSerializer, в protobuf-net из-за повышенной производительности, которую он предлагает, однако у меня возникают проблемы с этим конкретным случаем.
У меня есть объект [], который включает параметры, которые будут отправлены на удаленный хост (что-то вроде настраиваемой мини-функции rpc). Я знаю набор типов, из которых могут быть эти параметры, но я не могу заранее сказать, в каком порядке они будут отправлены.
У меня есть три ограничения. Во-первых, я работаю в Compact Framework, поэтому мне нужно что-то, что работает там. Во-вторых, как я уже упоминал, производительность - это серьезная проблема (на стороне сериализации), поэтому я бы предпочел избегать много размышлений, если это возможно. И самое главное, я забочусь о порядке, в котором эти параметры были отправлены.
Используя XmlSerializer, было просто добавить XmlInclude, но для полей нет ничего эквивалентного, насколько я знаю в Protobuf-net. Так есть ли способ сделать это? Вот упрощенный пример.
[Serializable]
[XmlInclude(typeof(MyType1)),
XmlInclude(typeof(MyType2)),
XmlInclude(typeof(MyType3))
public class Message()
{
public object[] parameters;
public Message(object[] parms)
{
parameters = parms;
}
}
Message m = new Message(new object[] {MyType1(), 33, "test",
new MyType3(), new MyType3()});
MemoryStream ms = new MemoryStream();
XmlSerializer xml = new XmlSerializer(typeof(Message));
xml.Serialize(ms,xml);
Это будет работать только с XmlSerializer, но если я попытаюсь преобразовать его в protobuf-net, я получу сообщение «Нет кодировки по умолчанию для объекта».
Лучшее, что я придумал, - это использование дженериков и [ProtoInclude], как показано в этом примере . Поскольку у меня могут быть разные типы объектов в массиве, это не совсем так. Я добавил общий список для каждого потенциального типа и свойство с [ProtoIgnore] с типом object [], чтобы добавить их и получить их. Я должен использовать отражение при добавлении их (чтобы знать, в какой массив помещать каждый элемент), что нежелательно, и я все еще не могу сохранить порядок, поскольку я просто извлекаю все элементы в каждом списке по одному и помещаю их в массив new object [] для свойства get.
Интересно, есть ли способ сделать это?
Я попробовал то, что предложил Марк ниже, но не смог заставить его работать. Я думаю, что я что-то неправильно понял.
Используя код, который вы написали. Я подумал, что должен использовать MessageParam Create для генерации объектов MessageParam для добавления в список. В общем, я добавил конструктор в Message так:
public Message(object[] parms)
{
foreach (object o in parms)
{
parameters.Add(MessageParam.Create(o));
}
}
Но, если я это сделаю, я получу «Неожиданный тип, найденный во время сериализации; типы должны быть включены в ProtoIncludeAttribute; найдено, что MessageParam`1 передан как MessageParam», поскольку я предполагаю, что сериализатор ожидает неуниверсальную версию. Я неправильно понял ваше предложение? Если так, что нужно сделать?