20

我对此完全感到困惑。我环顾四周,似乎找不到直接的答案。我有一个 .proto 文件,我的项目(全部是 java)用来创建一些消息。

有一个重复的信息字段。这是我们创建的一种类型。当我使用 protogen 生成 C# 类时,该字段显示为只读且没有设置器。

如果没有此参数,我无法完全构建消息。所以我的问题是。是否应该像这样生成重复字段并且我应该以其他方式访问这个只读列表?或者这是生成器中的错误?

生成的代码:

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; }
}

原型文件部分:

repeated StringMapEntry factoryProperty = 2;

我可能只是错过了一些非常明显的东西。谢谢你的帮助!

4

2 回答 2

36

该列表不是只读的...您只需更改它为您提供的列表

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

实际上,子集合只能获取是很常见的。这并不意味着您不能更改内容。

于 2013-05-17T22:36:50.897 回答
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&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>

我已经提取了私有字段和 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 的可疑条件。如果您只是删除这些,则该字段不再是只读的,并且设置器已正确生成。

所以它就变成了:私人的......剪断......

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&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>

我尝试将 optionXml 设置为 false,但它不起作用,您可能仍然希望启用该选项。

于 2015-02-18T16:50:46.590 回答