我对此完全感到困惑。我环顾四周,似乎找不到直接的答案。我有一个.proto文件,我的项目(全部是java)用来创建一些消息。
有一个重复的信息字段。这是我们创建的类型。当我用protogen生成C#类时,这个字段是只读的,没有setter。
如果没有此参数,我无法完全构建消息。所以我的问题是。是否应该像这样生成重复字段,我应该以其他方式访问此只读列表?或者这是生成器中的错误?
生成的代码:
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; }
}
Proto文件部分:
repeated StringMapEntry factoryProperty = 2;
我可能只是遗漏了一些非常明显的东西。谢谢你的帮助!
答案 0 :(得分:13)
列表不是只读的......你只是改变了它给你的列表:
var order = new Order();
order.Lines.Add( new OrderLine {...} );
子集合实际上很常见。这并不意味着你无法改变内容。
答案 1 :(得分:0)
在更新我们的proto-net可执行文件和相关文件后,这对我们来说也是一个新问题。这是我们以前没有经历的新行为。
在 csharp.xslt 中进行了一些挖掘后,我们找到了“重复”字段的定义:
<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>
我已经拿出了私有字段和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>
}
请注意$ optionXml上面的可疑条件。如果您只是删除它们,则该字段不再是只读的,并且正确生成了setter。
然后它变成: 私人......剪......
public ...snip...
{
...snip...
set { <xsl:value-of select="$field"/> = value; }
}
完整的'固定'模板:
<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>
我玩过将optionXml设置为false,但它没有用,你可能仍然希望启用该选项。