I have a server-client application in which I can modify both codebases. The client communicates with the server through numerous web services and I share some of the classes defined on the server side through Web Reference system. On the wire the data is sent using XML (SOAP). Also, I save some of the data on the disk using XmlSerializer
.
Due to rising performance issues, I want to migrate to a more sophisticated serializer with my eyes on Protocol Buffers and protobuf-net. I currently use protobuf-net v2 (r480, .NET 3.5)
The problem I seem to have is that classes shared through Web Reference system do not retain custom class/member attributes like ProtoContract
and ProtoMember
.
(But the serializer system does not throw the usual System.InvalidOperationException: Type is not expected, and no contract can be inferred
, leaving me with an empty stream. Is it because the class generated on the client side is marked as partial
?)
Example, server side:
[ProtoContract]
public class CommentStruct
{
[ProtoMember(1)] public int id;
[ProtoMember(2)] public DateTime time;
[ProtoMember(3)] public string comment;
[ProtoMember(4)] public int session;
}
Client side (generated code):
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://example.org")]
public partial class CommentStruct {
private int idField;
private System.DateTime timeField;
private string commentField;
private int sessionField;
/// <remarks/>
public int id {
get {
return this.idField;
}
set {
this.idField = value;
}
}
[...]
I managed to get around this issue using ProtoPartialMember
in an extra class file on the client side:
[ProtoContract,
ProtoPartialMember(1, "id"),
ProtoPartialMember(2, "time"),
ProtoPartialMember(3, "comment"),
ProtoPartialMember(4, "session")]
public partial class CommentStruct
{
}
The main concern here is: can I do this in a different way to avoid code duplication?
The other is: will I miss out on some of the protobuf-net goodies like inheritance support?
I have found some information about protobuf-net Visual Studio add-in. But as Marc Gravell has decribed it as an 'afterthought', I am reluctant to use it. Moreover, some of my co-developers are using VS Express editions that do not support add-ins.
Edit : What I meant as my main duplication concern is having to specify the class members and protobuf-net attributes twice - in a class definition on the server side and in partial class attributes on the client side.
As a minor point of terminology, I would avoid the word "shared" here, as "shared" typically means: as a library (which would work).
The reason it doesn't throw an error is not related to partial
; it is simply that protobuf-net is moderately happy to use the attributes of other libraries... within reason. For example, it will work with [XmlType]
/ [XmlElement(Order=n)]
and with [DataContract]
/ [DataMember(Order=n)]
. However, the code generated from the WSDL here does not include Order=n, so it doesn't see those as members needing to be serialized (it really needs the number).
The [ProtoPartialMember(...)]
usage (as you mention) is one way around this. It doesn't restrict you from other protobuf-net usage. [ProtoInclude(...)]
would still work (since you mention inheritance). Indeed, everything in protobuf-net can also be configured entirely at runtime, with zero attributes (via RuntimeTypeMode
). Re duplication: I can't see anything duplicated except the class name. Arguably, [ProtoInclude(...)]
is a bit of a duplication with [XmlInclude(...)]
, but not much.
I'm happy to believe I used the phrase in passing, but I'm not sure "afterthought" is really the main way I describe the add-in usage. To clarify: protobuf-net is primarily intended to fit the common .NET idiom of code-first (perhaps with attributes), rather than generating from a tool. It still works from either.
Of course, perhaps the easiest-of-all option, when available, is to simply share the .dll or the .cs. This works effortlessly with WCF / DataContractSerializer
, but I'm not sure that the older "web reference" web-services love this very much. Of course, there also isn't plug-in support for using protobuf-net as part of an older-style "web reference" ("asmx"), so you probably already need to change some things there...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.