1

Works:

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class ExcelData
{
    public int[] DataObjects { get; set; }
}

Don't work:

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class ExcelData
{
    public object[] DataObjects { get; set; }
}

My test:

[TestMethod]
public void ProtoWithObjectArray()
{
   var ex = new ProtoBufServiceClient(baseUrl);
   var res = ex.Get(new SelectWorksheetRange());
}

[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class SelectWorksheetRange : IReturn<ExcelData>
{
}

I don't even see error, because test just finish at ex.Get without any information. How to debug this?

Tomasito
  • 1,864
  • 1
  • 20
  • 43

1 Answers1

1

I cannot comment on ServiceStack, but as far as protobuf-net is concerned, yes: "int[] good, object[] bad". The reason is that the protobuf wire format (as designed by Google) is very terse and includes precisely zero metadata: it expects both ends of any conversation to know exactly what they are exchanging at any point. With int[], that is possible, and with object[] it simply isn't. There are some nasty ways of hacking around it, but they tend to be problematic (maintenance-wise) and inefficient.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Solution is to cast `object[]` as `byte[]` and transfer bytes? It is very simple thought. – Tomasito Mar 16 '14 at 12:04
  • @Tomasito that would only work if the data always actually is of the cast type. And if it is: it should be declared as such in the first place. Finally, correct me if I am wrong, but IIRC array variance only applies to arrays of reference types. Byte is not a reference type. – Marc Gravell Mar 16 '14 at 13:02
  • I'm writing service to share Excel worksheet data. This service is then used by another services and they will do casting from `object[]` to something meaningful. And all Excel interop functions returns objects. Now is OK when I put object[] into `MemoryStream` – Tomasito Mar 16 '14 at 13:26
  • @Tomasito at no point does one "put object[] into MemoryStream". A memory stream wraps a byte buffer: nothing more. Sure you can *serialize* to a memory-stream, but then you need to follow the rules of the chosen serilaizer. For this reason, it is not uncommon to use different DTO models with different serializers in a single application. – Marc Gravell Mar 16 '14 at 19:11