2013-05-17 42 views
6

我完全對此感到困惑。我環顧四周,似乎無法找到直接的答案。我有一個.proto文件,我的項目全部是java,用來創建一些消息。protobuf-net - .proto生成的類 - 是重複字段應該只讀而沒有setter?

有一個重複的信息字段。這是我們創建的類型。當我用Protogen生成C#類時,這個字段是隻讀的,沒有setter。

如果沒有此參數,我無法完全構建消息。所以我的問題是。重複字段應該是這樣生成的,我應該訪問此只讀列表其他方式?或者這是發生器中的錯誤?

生成的代碼:

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

原型文件部分:

repeated StringMapEntry factoryProperty = 2; 

,我可能只是失去了一些東西真的很明顯。謝謝你的幫助!

回答

10

列表不只讀...你剛剛發生變異列表它給你

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

它實際上是相當常見的子集是得到只。這並不意味着你不能改變內容。

+0

列表被創建爲私有隻讀,我想我只是沒有看到如何惹惱它。不過,稍後我將不得不看看它,我們用了一種不同的方法來解決這個問題,但我忘記了這一點。這可能只是我失明。感謝您的幫助!如果這是它的原因,我會回來並將其標記爲答案。 – Pewsplosions

+0

@user應該有一個公共財產。有沒有? –

+0

我將用代碼更新主帖,但我仍然沒有機會再次查看它。 – Pewsplosions

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"/>, [email protected]"<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([email protected]"<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可疑條件。如果您只刪除這些字段,則該字段不再是隻讀字段,而是可以正確生成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&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"/>, [email protected]"<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([email protected]"<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,但它沒」 t工作,你可能仍然希望啓用該選項。

+0

沒有'set'就意味着你不能'msg.field = null;'或'msg.field = otherList;'它並不妨礙你做'msg.field.Clear();'或者'msg.field.AddRange(otherList);'。 –

相關問題