K77 / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

DataContract Resolver Or surrogate needed. #114

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Hi
Is there any datacontract resolver to resolve inheritance problem?
or Does it support protobuf-net support surrogate?

thanks.

Original issue reported on code.google.com by sayya...@gmail.com on 14 Jun 2010 at 1:04

GoogleCodeExporter commented 9 years ago
It depends quite what you are after. In "v2", you can create the model at 
runtime, so you can construct a `RuntimeTypeModel` with the appropriate 
subtypes for your scenario (it must be possible to unambiguously resolve the 
integer ids to types, but that is a concern for the caller).

Does this solve the issue you are having?

Original comment by marc.gravell on 14 Jun 2010 at 1:22

GoogleCodeExporter commented 9 years ago
Hi,
I think it'd better that I explain my problem in detail. In our company we use 
an ORM made by ourselves. We keep Business Object properties value in a 
List<Object> and we serialize that list. I test different serialization 
mechanism on a usual object with 20 property. The result was awful because the 
DataContractSerializer serialization size is 1.5 times more thant 
binaryformatter ones.
Our orm is realy complicated so that when an usual class is serialized, it is 
equal to a Poco object with fairly 900 property. So i decide to search and find 
a better serializer for wcf.
I found your serializer but as I said my object property values are kept in a 
List<object> and your serializer needs and explicit type declaration.
I was wondering if you could help me.
sayyaari@gmail.com

Original comment by sayya...@gmail.com on 15 Jun 2010 at 11:08

GoogleCodeExporter commented 9 years ago
List<object> is fine for type-based serializers, but most contract-based 
serializers will fail with that. That said, there is no *fundamental* reason it 
can't do that - simply it is pretty chaotic. Both the released code and the 
in-progress ("v2") code support non-generic usage, but to avoid too much 
bizarreness it currently precludes against `object` as a base-type. Is there, 
for example, any common base-type in your model? Making it work with *just* 
`object` is a real pain, but there may be options if there is anything else.

But to explain; the protobuf wire format (devised by Google, so out of my 
hands) doesn't include type information on the wire. It assumes you *know* what 
you are expecting. I can fudge around a lot of this with some creative nesting 
(which is how protobuf-net implements inheritance support).

Original comment by marc.gravell on 15 Jun 2010 at 11:25

GoogleCodeExporter commented 9 years ago
Hi,
Thanks for your reply.
As you know in .net 4 DataContractSerializer can accept a DataContractResolver 
which would be requested for type resolution. 
Also i wrote a semi Contract type resolver by writing my custom surrogate in 
.net 3.
And now i am really disappointed because serialization size is really large 
despite of it took shorter than binaryformatter.
Is there any way that your serializer request some contract resolver? I need 
more control over serialization.

Original comment by sayya...@gmail.com on 15 Jun 2010 at 11:42

GoogleCodeExporter commented 9 years ago
At the moment, in "v2" you can essentially do this ahead-of-time (but at 
runtime) by telling it the map between types and keys (simply integers). I 
*guess* it could do this on the fly as well, but it doesn't offer that at the 
moment.

However; an interesting option might be to to use a hybrid; let the inbuilt 
serializer worry about type resolution, and use protobuf-net for the 
materialization. This is supported for BinaryFormatter via ISerializable, using 
protobuf-net to perform the internal serialization. I can't think of a reason 
the same approach shouldn't apply for DCS; you'd have a DCS shell, with a 
base-64 chunk in the middle of it (or ripped and sent separately if MTOM spots 
it). Would this approach be of interest?

Original comment by marc.gravell on 15 Jun 2010 at 12:14

GoogleCodeExporter commented 9 years ago
Example (note that in .NET 4.0 I had to tweak the engine a tiny bit to make 
this work properly; looks like something changed in XmlReader):

    [XmlType]
    class Foo : IXmlSerializable {
        public System.Xml.Schema.XmlSchema GetSchema() { return null; }
        public void ReadXml(System.Xml.XmlReader reader) { Serializer.Merge(reader, this); }
        public void WriteXml(System.Xml.XmlWriter writer) { Serializer.Serialize(writer, this); }

        [XmlElement(Order=1)] public int Id {get;set;}
        [XmlElement(Order = 2)] public float Value { get; set; }
        [XmlElement(Order=3)] public string Name {get;set;}
    }

    static class Program {
        static void Main() {
            var dcs = new DataContractSerializer(typeof(Foo));
            var obj = new Foo { Id = 123, Value = 123.45F, Name = "abc"};
            // write to console
            using (var writer = XmlWriter.Create(Console.Out)) { dcs.WriteObject(writer, obj); }
            // round-trip in memory
            Foo clone;
            using (var ms = new MemoryStream()) {
                dcs.WriteObject(ms, obj);
                ms.Position = 0;
                clone = (Foo)dcs.ReadObject(ms);
            }
            Console.WriteLine(clone.Id);
            Console.WriteLine(clone.Value);
            Console.WriteLine(clone.Name);
        }

Original comment by marc.gravell on 15 Jun 2010 at 12:35