Protobuf-net - generated class from .proto - should the repeating field be read-only without configuration?

I am completely confused by this. I looked around and could not find a direct answer. I have a .proto file that my project, which was all java, uses to create some messages.

A duplicate Info field appears. What type we created. When I generate C # classes using a protogen, this field appears as read-only and has no setter.

I cannot completely create a message without this parameter. So my question is. Are duplicate fields that should be generated this way, and should I access this read-only list in a different way? Or is it a mistake in the generator?

Generated Code:

private readonly global::System.Collections.Generic.List<StringMapEntry> _factoryProperty = new global::System.Collections.Generic.List<StringMapEntry>(); [global::ProtoBuf.ProtoMember(2, Name=@ "factoryProperty", DataFormat = global::ProtoBuf.DataFormat.Default)] public global::System.Collections.Generic.List<StringMapEntry> factoryProperty { get { return _factoryProperty; } } 

Protocol File Section:

 repeated StringMapEntry factoryProperty = 2; 

I probably just missed something really obvious. Thanks for any help!

+6
source share
2 answers

The list is not readable only ... You just change the list that it gives you:

 var order = new Order(); order.Lines.Add( new OrderLine {...} ); 

In fact, quite often, only sub-categories can be accessed. This does not mean that you cannot change the content.

+10
source

This was a new problem for us, and also after updating the prototype executable files and related files. This was a new behavior that we have not experienced before.

After a little digging in csharp.xslt, we found a definition for "repeating" fields:

 <xsl:template match="FieldDescriptorProto[label='LABEL_REPEATED']"> <xsl:variable name="type"><xsl:apply-templates select="." mode="type"/></xsl:variable> <xsl:variable name="format"><xsl:apply-templates select="." mode="format"/></xsl:variable> <xsl:variable name="field"><xsl:apply-templates select="." mode="field"/></xsl:variable> private <xsl:if test="not($optionXml)">readonly</xsl:if> global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List&lt;<xsl:value-of select="$type"/>&gt;(); [<xsl:apply-templates select="." mode="checkDeprecated"/>global::ProtoBuf.ProtoMember(<xsl:value-of select="number"/>, Name=@ "<xsl:value-of select="name"/>", DataFormat = global::ProtoBuf.DataFormat.<xsl:value-of select="$format"/><xsl:if test="options/packed='true'">, Options = global::ProtoBuf.MemberSerializationOptions.Packed</xsl:if>)]<!-- --><xsl:if test="$optionDataContract"> [global::System.Runtime.Serialization.DataMember( Name=@ "<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>, IsRequired = false)] </xsl:if><xsl:if test="$optionXml"> [global::System.Xml.Serialization.XmlElement(@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>)] </xsl:if> public global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:call-template name="pascal"/> { get { return <xsl:value-of select="$field"/>; }<!-- --><xsl:if test="$optionXml"> set { <xsl:value-of select="$field"/> = value; }</xsl:if> } </xsl:template> 

I pulled out specific parts for the private field and setter:

 private <xsl:if test="not($optionXml)">readonly</xsl:if> ...snip... public ...snip... { ...snip... <!----><xsl:if test="$optionXml"> set { <xsl:value-of select="$field"/> = value; } </xsl:if> } 

Note the suspicious conditions above for $ optionXml. If you simply delete them, the field will no longer be readonly, and the setter will be generated correctly.

So then it becomes: private ... snip ...

 public ...snip... { ...snip... set { <xsl:value-of select="$field"/> = value; } } 

Full "fixed" template:

  <xsl:template match="FieldDescriptorProto[label='LABEL_REPEATED']"> <xsl:variable name="type"><xsl:apply-templates select="." mode="type"/></xsl:variable> <xsl:variable name="format"><xsl:apply-templates select="." mode="format"/></xsl:variable> <xsl:variable name="field"><xsl:apply-templates select="." mode="field"/></xsl:variable> private global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List&lt;<xsl:value-of select="$type"/>&gt;(); [<xsl:apply-templates select="." mode="checkDeprecated"/>global::ProtoBuf.ProtoMember(<xsl:value-of select="number"/>, Name=@ "<xsl:value-of select="name"/>", DataFormat = global::ProtoBuf.DataFormat.<xsl:value-of select="$format"/><xsl:if test="options/packed='true'">, Options = global::ProtoBuf.MemberSerializationOptions.Packed</xsl:if>)]<!-- --><xsl:if test="$optionDataContract"> [global::System.Runtime.Serialization.DataMember( Name=@ "<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>, IsRequired = false)] </xsl:if><xsl:if test="$optionXml"> [global::System.Xml.Serialization.XmlElement(@"<xsl:value-of select="name"/>", Order = <xsl:value-of select="number"/>)] </xsl:if> public global::System.Collections.Generic.List&lt;<xsl:value-of select="$type" />&gt; <xsl:call-template name="pascal"/> { get { return <xsl:value-of select="$field"/>; } set { <xsl:value-of select="$field"/> = value; } } </xsl:template> 

I played with setting the XML option to false, but that did not work, and you can still enable this option anyway.

0
source

Source: https://habr.com/ru/post/945302/


All Articles