2013-05-17 18 views
6

Sono totalmente confuso su questo. Mi sono guardato intorno e non riesco a trovare una risposta diretta. Ho un file .proto che il mio progetto, che è stato tutto java, usa per creare alcuni messaggi.protobuf-net - classe generata da .proto - Il campo ripetuto dovrebbe essere di sola lettura senza setter?

C'è un campo Info ripetuto. Che è un tipo che abbiamo creato Quando genero le classi C# con protogen, questo campo si presenta come di sola lettura e non ha setter.

Impossibile compilare completamente il messaggio senza questo parametro. Quindi la mia domanda è. Si suppone che i campi ripetuti vengano generati in questo modo e io dovrei accedere a questa lista di sola lettura in un altro modo? O è un bug nel generatore?

codice generato: sezione del file

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

Proto:

repeated StringMapEntry factoryProperty = 2; 

ero probabilmente solo perdendo qualcosa di davvero evidente. Grazie per qualsiasi aiuto!

risposta

10

L'elenco non è di sola lettura ... Basta mutazione del 'lista ti dà:

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

In realtà è abbastanza comune per i sotto-collezioni da ottenere solo. Ciò non significa che non puoi cambiare il contenuto.

+0

L'elenco è stato creato come privato di sola lettura, suppongo che io non stia proprio vedendo come fare a casaccio. Dovrò guardarlo dopo, però, abbiamo usato un approccio diverso al problema e me ne sono dimenticato. Probabilmente sono solo io che sono cieco. Grazie per l'aiuto! Se questo è quello che è stato, tornerò indietro e segnerò la risposta. – Pewsplosions

+0

@user ci dovrebbe essere una proprietà pubblica. Non c'è? –

+0

Aggiornerò il post principale con il codice, ma non ho ancora la possibilità di verificarlo di nuovo. – Pewsplosions

0

Questo era un nuovo problema anche per noi dopo l'aggiornamento del file eseguibile proto-net e dei file correlati. Era un nuovo comportamento che non avevamo mai sperimentato prima.

Dopo un po 'di scavo in csharp.xslt, abbiamo trovato la definizione per i campi 'ripetuti':

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

ho tirato fuori le parti specifiche per il settore privato e il 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> 
} 

Notare le condizioni sospette sopra per $ optionXml. Se li rimuovi, il campo non è più in lettura e il setter è generato correttamente.

Così diventa allora: privato ... snip ...

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

completa template 'fisso':

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

ho giocato con l'impostazione optionXml a false, ma didn' funziona e potresti comunque volere che l'opzione sia abilitata comunque.

+0

Non avere il 'set' significa solo che non puoi fare' msg.field = null; 'o' msg.field = otherList; 'Non ti impedisce di fare' msg.field.Clear(); 'oppure 'msg.field.AddRange (altralista);'. –