Reputation: 1357
I am trying to serialize an array of my dataobjects through WCF with protobuf-net.
If I serialize the Array of my dataobjects manually, it works successfully:
var proto = Serializer.CreateFormatter<DataType[]>();
which is way faster and smaller than the ordinary binary xml DataContractSerializer
- thats why I wanna use it!
The 'DataType' class is just an example - I have many of those. When the reponse of my service is just a single object, everything works just fine.
But when my service returns an Array of objects it seems it does not know what to do and uses the ordinary DataContractSerializer
.
The ProtoBehavior is applied:
endpoint.Behaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
My dataobject is more or less like that:
[Serializable]
[DataContract]
[ProtoContract]
public class DataType
{
[DataMember(EmitDefaultValue = false, Name = "K")]
[ProtoMember(1)]
public string Key { get; set; }
// many more to come
}
and that's basically my service:
[ServiceContract(CallbackContract = typeof(IBaseDataObjectUpdate), SessionMode = SessionMode.Required)]
[ServiceKnownType("GetKnownTypes", typeof(KnownTypesProvider))]
public interface IDataTypeService
{
[OperationContract]
DataType[] Load(Filter[] filter, Guid clientGuid);
// some more
}
I could track it down to the TryCreate
in the XmlProtoSerializer
. The call:
int key = GetKey(model, ref type, out isList);
does not return a valid key, therefore no XmlProtoSerializer
is created.
That explains the behavior, but what are my options here?
I found an old answer of Marc Gravell where he suggests the creation of an object which consists of the Array. But as it is from 2011 it might be outdated: https://stackoverflow.com/a/6270267/2243584
Or can I add the model to protobuf-net somehow manually? As mentioned above the manual serialization is working.
Any comment is appreciated!
Upvotes: 2
Views: 846
Reputation: 1357
OK, so far I have come up with 2 solutions.
I have adapted the method internal static Type GetListItemType(TypeModel model, Type listType)
in the TypeMode class as follows:
if (listType.IsArray) // NEW
{
if (listType.GetElementType() == typeof(byte))
return null;
}
if (listType == model.MapType(typeof(string)) // || listType.IsArray // CHANGED!!!
|| !model.MapType(typeof(IEnumerable)).IsAssignableFrom(listType)) return null;
I think I did figure out why arrays are excluded. Because if you support byte[], you get some problems when finally sending the data to the wire. At least I got some Assert and exception in the encode factory when dealing with byte[].
As I have no idea on the side effects of solution Nr. 2 - I stick with solution Nr. 1.
Nevertheless I am quite keen on a comment from Marc - of course, everybody is welcome!
Upvotes: 2