17

I have an assembly with DataContracts and I need to generate .proto schema for it to be able to exchange the data with java system. The DataContracts code can be changed but I cannot add [ProtoContract] and [ProtoMember] attributes in it because it will result in protobuf-net assembly dependency. We use WCF in C# parts of the system so we would not want to have dependency on proto-buf assembly in most of C# projects that don't work with java system.

On the protobuf-net site in a GettingStarted section it's said that:

Don't Like Attributes?
In v2, everything that can be done with attributes can also be configured at runtime via RuntimeTypeModel.

However I've no clue how to actually configure serialization without attributes and I haven't seen any examples of that.

I'm trying to do

[DataContract]
public class MyEntity
{
    [DataMember(Order = 1)]
    public String PropertyA { get; set; }

    [DataMember(Order = 2)]
    public int PropertyB { get; set; }
}

RuntimeTypeModel.Default.Add(typeof(MyEntity), false);

string proto = Serializer.GetProto<MyEntity>();

And get the following as the value of proto

package ProtobufTest;

message MyEntity {
}
Mike
  • 2,468
  • 3
  • 25
  • 36

1 Answers1

14

Clarification: most of this answer relates to the pre-edit question, where false was passed to RuntimeTypeModel.Add(...)


I've used your exact code (I inferred that this was in namespace ProtobufTest, but the rest was copy/paste from the question) with r2.0.0.640 (the current NuGet deployment), and I get:

package ProtobufTest;

message MyEntity {
   optional string PropertyA = 1;
   optional int32 PropertyB = 2 [default = 0];
}

Further, you get the exact same result even if you remove the RuntimeTypeModel.Default.Add(...) line.

It is unclear to me why you are seeing something different - can you clarify:

  • which protobuf-net version you are using exactly
  • if those [DataContract] / [DataMember] attributes are the System.Runtime.Serialization.dll ones, or your own (sorry if that seems a bizarre question)

To answer the question fully: if you couldn't have any attributes (and the ones you have are just fine), you could also do:

RuntimeTypeModel.Default.Add(typeof(MyEntity), false)
    .Add(1, "PropertyA")
    .Add(2, "PropertyB");

which would configure PropertyA as key 1, and PropertyB as key 2.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thanks for quick response! I use the same version. The second parameter in my `RuntimeTypeModel.Default.Add(typeof(MyEntity), ...)` was actually `false`. With `true` or without that call at all I get the same result as you do. – Mike Jun 19 '13 at 21:35
  • @Mike ah, right; yes, that `false` means "don't look at the attributes", which includes not looking at the `DataMember(Order=n)` attributes. If you pass `false`, you need to configure it *manually* - which is what I have done in the last example above. If you want to use the `DataMember(Order=n)` attributes: say `true` – Marc Gravell Jun 19 '13 at 21:37
  • By the way, it would be nice to have those `.Add(1, "PropertyA")` parts to accept Expression as the second parameter for the strong-typing and compiler checking :) This will ease working with non-attributed types. – Mike Jun 19 '13 at 21:37
  • @Mike well, you could always add an extension method; I've deliberately limited the dependencies - mostly it only currently uses 2.0, and 3.0 if you want the WCF support; heck, it will even compile for .NET 1.1 if you really want. Adding a 3.5 dependency *just* for `Expression` seems a bit overkill. – Marc Gravell Jun 19 '13 at 21:39
  • Makes total sense. The extension is pretty trivial to implement myself. – Mike Jun 19 '13 at 21:53