2010-07-16 9 views
7

Frage: Ich benutze eine serialisierbare Wörterbuchklasse, die Sie unter http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx finden, um ein Wörterbuch zu serialisieren. Was gut funktioniert, aber ich stoße auf ein lästiges Problem.Serialisierbares Wörterbuch, wie wird der Schlüsselname eingestellt?

 <System.Xml.Serialization.XmlRoot("DataBase")> _ 
    Public Class cDataBase 
     <System.Xml.Serialization.XmlNamespaceDeclarations()> _ 
     Public ns As New System.Xml.Serialization.XmlSerializerNamespaces() 


     <System.Xml.Serialization.XmlElement("Tables")> _ 
     Public Tables1 As New SerializableDictionary(Of String, cTable) 


    End Class ' cDataBase 

Wenn ich serialisiert Instanzen der oben genannten Klasse, wie diese, die erzeugte XML wie folgt aussieht:

<Tables> 
<item> 
    <key> 
    <string>MyTable</string> 
    </key> 
    <value> 
    <Table CreationDate="0001-01-01T00:00:00" LastModified="0001-01-01T00:00:00"> 
     <Columns> 
     <Column Name="PrimaryKeyName"> 
      <DataType>Uniqueidentifier</DataType> 
      <Length>36</Length> 
     </Column> 
     </Columns> 
     <Rows> 
     <Row> 
      <Item>Reihe1</Item> 
      <Item>Reihe2</Item> 
      <Item>Reihe3</Item> 
     </Row> 
     <Row> 
      <Item>Reihe1</Item> 
      <Item>Reihe2</Item> 
      <Item>Reihe3</Item> 
     </Row> 

Welche wäre gut, wenn ich nur könnte herausfinden, wie der Schlüssel zum Umbenennen von <String> etwas in einem Attribut definiert

<key> 
    <string>MyTable</string> 
    </key> 

im Grunde so etwas wie die XmlArrayItem Attribut, wie unten, wenn (nur) das Wörterbuch ein Array ist ...

 <System.Xml.Serialization.XmlArray("Tables")> _ 
     <System.Xml.Serialization.XmlArrayItem("Table")> _ 
     Public Tables As New List(Of cTable) 

ich von String geerbt, die ich mit einem Namen ausstatten könnte, String zu einer benutzerdefinierten Klasse zu ändern versuchen wollte aber das problem ist, man kann nicht von string erben ...

Antwort

0

Sie könnten die Dictionary-Vorlage spezialisieren oder von einer Spezialisierung ableiten, um zu serialisieren, wie Sie möchten.

1

Wenn ich Ihre Frage richtig zu lesen, möchten Sie Ihre serialisierte Ausgabe von diesem ändern:

<Tables> 
    <item> 
    <key> 
     <string>MyTable</string> 
    </key> 
    <value> 
     <!-- snip --> 
    </value> 
    </item> 
</Tables> 

Um so etwas wie dieses:

<Tables> 
    <item> 
    <key> 
     <TableId>MyTable</TableId> 
    </key> 
    <value> 
     <!-- snip --> 
    </value> 
    </item> 
</Tables> 

Sie erwähnen auch, dass ein Weg könnten Sie Erreiche dies, um deinen eigenen Typ zu erstellen, der von System.String erbte, was - wie du auch erwähnst - offensichtlich nicht möglich ist, weil es sealed ist.

Sie können jedoch das gleiche Ergebnis erzielen, indem der Schlüsselwert in der eigenen Art Einkapseln und Steuern dann die XmlSerializer Ausgabe unter Verwendung eines XmlTextAttribute (siehe MSDN):

standardmäßig die XmlSerializer serialisiert ein Klassenmitglied als XML Element. Wenn Sie jedoch das XmlTextAttribute auf ein Mitglied anwenden, übersetzt der XmlSerializer seinen Wert in XML-Text. Dies bedeutet, dass der Wert in den Inhalt von einem XML-Element codiert ist.

In Ihrem Fall würden Sie das Attribut wie folgt verwenden:

public class TableId 
{ 
    [XmlText] 
    public string Name 
    { 
     get; 
     set; 
    } 
} 

Und dann diese Art als Schlüssel verwenden (en) Ihrer Dictionary. Welches sollte erreichen, was Sie wollen.

0

Obwohl es wahrscheinlich etwas vom Thema entfernt ist, muss ich fragen, warum XML verwenden, um es zu serialisieren? Wenn Sie nur den Objektstatus für die Zukunft speichern möchten, würde ich JSON anstelle von XML vorschlagen.

Ein großer Vorteil ist, dass Sie ganz einfach eine normale Dictionary-Klasse speichern können, ohne einen speziellen Code schreiben zu müssen. Die Nutzlast ist auch viel kleiner als JSON, also ist es ein großartiges Format, um bei Bedarf über die Leitung zu senden.

Scott Gu hat ein paar Informationen über die Verwendung des JavascriptSerializer here. Ich würde vorschlagen, es zu einer Erweiterungsmethode für Objekte zu machen. Dann können Sie dies tun:

Dictionary<int, string> myDict = new Dictionary<int,string>(); 
myDict.Add(10,"something"); 
string jsonData = myDict.ToJSON(); 

Ist dies etwas, das Ihr Interesse an lassen Sie mich ist wissen und ich kann den Code für die Erweiterungsmethoden poste ich verwenden. (sry nicht bei der Arbeit und ich habe sie nicht hier bei mir.)

+0

Erstens bin ich begrenzt auf .NET 2.0, und zweitens, das Hauptproblem ist, dass Wörterbuch ein generischer Typ ist und NICHT SERIALIZABLE (ebenfalls nicht in JSON). Ich bin in XML serialisieren, weil XML breiter verwendet wird, und besser zu lesen, wenn serialisiert von .NET 2.0. –

0

Da Sie die Quelle haben, können Sie sie so ändern, dass sie XML-Attribute nachschaut, wenn sie vorhanden sind. Es gibt nichts sakrales über die XML-Attributfamilie - sie sind genau wie jedes andere Attribut, das durch Reflektion nachgeschlagen werden kann. Sobald Sie das getan haben, können Sie neue Namen in den Code eingeben, in dem Sie XML-Tags lesen und/oder lesen. Sie können auch zwei Params hinzufügen, um Variablennamen wie ReadXml (myReader, "Tables", "Table") explizit zu überschreiben und den Code so zu ändern, dass er diesen Namen anstelle der Standardwerte folgt. Ich muss allerdings zu C# wechseln :-)

0

Überlegen Sie, das Wörterbuch durch KeyedCollection zu ersetzen. Es wird als Liste serialisiert, daher ist es kleiner und XML-Knotennamen sind Namen von cTable-Eigenschaften/-Feldern.

[Serializable] 
[CollectionDataContract] 
public class TablesCollection : KeyedCollection<string, cTable> 
{ 
    protected override string GetKeyForItem(cTable item) 
    { 
     return item == null ? String.Empty : item.TableName; 
    } 
} 
0

kann nicht sagen, dass ich, dass die Umsetzung von serializeable Wörterbuch verwendet habe, aber falls Sie bereit, neue Dinge zu versuchen, eine wenig bekannte abstrakte Klasse wird KeyedCollection genannt, die voll serializeable ist, Schlüssel unterstützt basierter Zugriff und kann leicht als Wörterbuch implementiert werden.

.Net 2.0 Keyed Collection