2010-07-16 10 views
7

Pregunta: Utilizo una clase de diccionario serializable, que se encuentra en http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx , para serializar un diccionario. Lo que funciona bien, pero me encuentro con un problema molesto.Diccionario serializable, cómo configurar el nombre de la tecla?

 <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 

Cuando serializar instancias de la clase anterior, ya que esto, el xml creado se ve así:

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

que sería bueno si sólo pudiera encontrar la manera de cambiar el nombre de la clave de <cadena> a algo definido en un atributo

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

Básicamente algo así como el XmlArrayItem atributo, como más abajo, si (sólo) el diccionario eran una serie ...

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

que quería probar a cambiar de cuerda a una clase personalizada heredada de la cadena, que podría dotar de un nombre, pero el problema es que uno no puede heredar de una cadena ...

Respuesta

0

Puede especializar la plantilla del diccionario o derivar de una especialización para serializar como desee.

1

Si estoy leyendo bien su pregunta, si desea cambiar su salida serializada de esto:

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

Para algo como esto:

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

También menciona que una manera que pudiera lograr esto sería crear su propio tipo heredado de System.String, que, como usted también menciona, obviamente no es posible porque es sealed.

Usted puede sin embargo conseguir el mismo resultado mediante la encapsulación del valor clave en su propio tipo, y luego controlar la salida XmlSerializer utilizando un XmlTextAttribute (ver MSDN):

Por defecto, los XmlSerializer Serializa un miembro de clase como un elemento XML . Sin embargo, si aplica el XmlTextAttribute a un miembro, el XmlSerializer traduce su valor en texto XML. Esto significa que el valor está codificado en el contenido de un elemento XML.

En su caso tendrá que utilizar el atributo de la siguiente manera:

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

y luego usar este tipo como la clave (s) a su Dictionary. Que debería lograr lo que quieres.

0

Aunque probablemente esté fuera de tema, necesito preguntar por qué usar XML para serializarlo? Si solo quiere guardar el estado del objeto para el futuro, sugeriría JSON en lugar de XML.

Una gran ventaja es que puede guardar fácilmente una clase de diccionario normal sin tener que escribir ningún código especial. La carga útil también es mucho más pequeña que JSON, por lo que es un gran formato para enviar a través del cable si es necesario.

Scott Gu tiene un poco de información sobre el uso del JavascriptSerializer here. Sugeriría que sea un método de extensión en el objeto. A continuación, puede hacer esto:

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

Si esto es algo que su interés en que me haga saber y me pueden enviar el código de los métodos de extensión que uso. (no está en el trabajo y no los tengo aquí).

+0

En primer lugar, estoy limitado a .NET 2.0, y en segundo lugar, el problema principal es que el diccionario es un tipo genérico y no SERIALIZABLE (no en JSON tampoco). Estoy serializando en XML porque XML es más amplio y mejor de leer, si se serializa desde .NET 2.0. –

0

Como tiene la fuente, puede modificarla para que busque atributos XML si están presentes. No hay nada sacro sobre la familia de atributos XML: son como cualquier otro attrib que se puede buscar a través de la reflexión. Una vez que lo tenga, puede poner nuevos nombres en el código donde creater y/o lee etiquetas XML. También puede agregar 2 parámetros para anular explícitamente nombres de etiquetas, como ReadXml (myReader, "Tablas", "Tabla") y cambiar el código para seguir estos nombres en lugar de los valores predeterminados. Tiene que cambiar a C# aunque :-)

0

Considere reemplazar el diccionario con KeyedCollection. Se serializa como una lista, como resultado es más pequeño y los nombres de nodo XML son nombres de propiedades/campos de cTable.

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

no se puede decir que he utilizado que la aplicación de diccionario serializeable, pero en caso de que esté dispuesto a probar cosas nuevas, hay una pequeña clase abstracta conocido llamado KeyedCollection que es totalmente serializeable, apoya clave acceso basado, y se puede implementar fácilmente como diccionario.

.Net 2.0 Keyed Collection

Cuestiones relacionadas