سؤال

Does protobuf-net support nested classes ?

Are the attributes type names and order correct ?

as the code below, using alternative attribute XmlType/XmlElement instead ProtoContract/ProtoInclude

     using System.Xml.Serialization;

    [XmlType("Person")]
    public class Person
    {
      [XmlElement(ElementName = "Display Name",Order = 1)]
      public string Name { get; set; }

      [XmlElement(ElementName = "Age", Order = 2)]
      public byte  Age { get; set; }

      [XmlType("Person.Address")]
      public class Address
      {
          [XmlElement(ElementName = "Street",Order = 1)] 
           // before I had  Order=3 to be unique, but as Mark says 
           // the "Order  only needs to be unique inside a single type"
          public string Street { get; set; }

          [XmlElement(ElementName = "ZIP",Order =2)]
          public string Zip { get; set; }

      }        
   }

Update, in my answer below, I wrote the final class, implementing a ServiceStack service with protobuf.

هل كانت مفيدة؟

المحلول

With Marc Gravell's help, I understood how nested classes work in protobuf.

I tested it with a ServiceStack (ver. 3.9.71) service, and it works fine.

here is the model.

using System.Xml.Serialization;

[XmlType("Person")]
public class Person
{
     [XmlElement(ElementName = "Display Name", Order = 1)]
     public string Name { get; set; }

     [XmlElement(ElementName = "Age", Order = 2)]
     public byte Age { get; set; }

     [XmlElement(ElementName = "Contact Address", Order =3)] // the address instance
     public Address ContactAddress { get; set; }

     [XmlElement(ElementName = "Person Id", Order = 4)]
     public int  Id { get; set; }

        [XmlType("Person.Address")]
        public class Address
        {
          [XmlElement(ElementName = "Street", Order = 1)]
          // before I had  Order=5 to be unique, but as Mark says 
          // the "Order  only needs to be unique inside a single type"
          public string Street { get; set; }

         [XmlElement(ElementName = "ZIP", Order = 2)]
         public string Zip { get; set; }

       }
}

the ServiceStack Requests

     public class PersonRequest
      {
        public string Zip { get; set; }
        public byte Age { get; set; }
        public int Id { get; set; }
      }
     public class AddressRequest
     {
       public string Zip { get; set; }

     }

the ServiceStack Routes in AppHost.Configure. ( self-hosted service)

   Routes        
      .Add<PersonRequest>("/Person/{Id}", "GET, OPTIONS")
      .Add<PersonRequest>("/Persons/{Zip}", "GET, OPTIONS")

      .Add<AddressRequest>("/Addresses/{Zip}", "GET, OPTIONS");

the services

First case, we ask a list of Persons with Contact Address using Zip filter

Second case, a list of Addresses using Zip filter, unrelated to Persons

public List<Person>  Get(PersonRequest request)
{
  List<Person> persons=new List<Person>();
  persons.Add(new Person()
  { Name = "stefan", ContactAddress = new Person.Address(){Street="North Pole"}});
    return  persons;
}
public List<Person.Address>  Get(AddressRequest request)
{    // it returns only addresses filtered by Zip
  List<Person.Address> addresses=new List<Person.Address>();         
  addresses.Add( new Person.Address() { Street = "North Pole" }  );
  return  addresses;
}

the ServiceStack client code, using the ProtoBufServiceClient

 using ServiceStack.Plugins.ProtoBuf;
        ...
 var client = new ProtoBufServiceClient(serverUri);
 List<Person> persons = client.Get<List<Person>>(serverUri + @"/Persons/600617");
 List<Person.Address> addresses = 
               client.Get<List<Person.Address>>(serverUri + @"/Addresses/600617");

thanks a lot, Marc.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top