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<<xsl:value-of select="$type" />> <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List<<xsl:value-of select="$type"/>>(); [<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<<xsl:value-of select="$type" />> <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<<xsl:value-of select="$type" />> <xsl:value-of select="$field"/> = new global::System.Collections.Generic.List<<xsl:value-of select="$type"/>>(); [<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<<xsl:value-of select="$type" />> <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.