2010-08-09 3 views
6

Je suis en train de sérialiser un dictionnaire en XML. Lorsque je crée un nouveau dictionnaire que j'utilise le constructeur pour fournir EqualityComparer sans boîtier par exempleDictionnaire de sérialisation <chaîne, objet> lorsque le dictionnaire a été initialisé avec une chaîne insensible à la casse.

var tabs = new Dictionary<string,Tab>(StringComparer.OrdinalIgnoreCase); 

Je sérialiser ensuite XML et quand je deserialize informations sur boîtier est perdu - la désérialisation est faite au dictionnaire avec GenericEqualityComparer, qui Apparemment, il est sensible à la casse car il ne trouve pas mes clés si elles ne sont pas correctement placées.

Des idées comment puis-je le changer? Un moyen serait de créer un nouveau dictionnaire et de copier les données de la désérialisée vers la nouvelle, mais cela semble gênant.

MISE À JOUR:

Le désérialisation a travaillé tout le temps, il est juste que ce désérialise le Dictionnaire sérialisé à celui qui n'utilise pas les clés de la casse.

+0

Est-ce que ce problème se produit lorsque vous utilisez DataContract? –

+0

oui, la classe qui contient une propriété de type Dictionary est marquée DataContract et cette propriété est marquée DataMbember, si c'est ce que vous vouliez savoir – mare

+0

Oui, ça l'était, mais maintenant que vous avez compris qu'il fonctionne dans .NET 4.0, il n'y a rien pour moi de suivre. Félicitations pour résoudre votre propre problème. –

Répondre

4

Je sais que cette question est assez ancienne, mais je me suis récemment retrouvé à chercher comment faire. En utilisant .Net4 (comme @mare dit), vous pouvez créer de très jolies méthodes d'extension pour que cela devienne un jeu d'enfant. Découvrez https://stackoverflow.com/a/5941122/435460 pour une mise en œuvre agréable et simple. Après beaucoup de fouilles, cela a fonctionné comme un charme pour moi.

3

Edit:

par les commentaires, il semble que cette approche peut être dépassée dans .NET 4.

Fin Modifier

dictionnaires se passent d'exiger un peu d'aide à la sérialisation et la désérialiser.

Voici un bon exemple d'un dictionnaire XML Serializable:

http://weblogs.asp.net/pwelter34/archive/2006/05/03/444961.aspx

Vous pouvez le rendre insensible à la casse en changeant la déclaration de classe et l'ajout d'un constructeur, et tordant une ligne.

** EDIT: erreur de syntaxe corrigée ci-dessous./EDIT **

public class SerializableDictionary<TValue> 
    : Dictionary<string, TValue>, IXmlSerializable 
{ 
    public SerializableDictionary() 
     : base(StringComparer.InvariantCultureIgnoreCase) 
    { 
    } 

    // ... 
} 

Modifier la ligne this.Add(key, value); à this[key] = value;. Quoi qu'il en soit, il se peut que vous deviez masser certains détails, mais cela devrait vous permettre de bien marcher sur la route.

+0

En travaillant avec .NET 4, il semble que le dictionnaire générique est sérialisable, car il fonctionne pour moi. Je ne suis pas sûr que l'implémentation d'une solution à partir de 2006 est recommandée, étant donné que la nouvelle implémentation de Dictionary ou l'implémentation de DataContractSerializer prend en charge la sérialisation/désérialisation de Dictionnaire prête à l'emploi. – mare

+0

@mare: Hey, c'est une bonne nouvelle! S'il vous plaît envisager de mettre à jour le tag .NET 4, et je vais placer une modification sur mon message. – kbrimington

+0

Ne compile pas car 'La déclaration de paramètre Type doit être un identifiant et non un type' pour' string' dans 'SerializableDictionary '. – JoeBilly

1

Il vous suffit de terminer votre nouveau dictionnaire dans le constructeur:

Dictionary<string, Tab> tabs ; 
tabs = new Dictionary<string, Tab>((Dictionary<string, Tab>)serializer.ReadObject(reader),StringComparer.OrdinalIgnoreCase); 
1

Une vieille question que je me rends compte, mais était juste en train de creuser à travers la source de Dictionary et a remarqué qu'il devrait en fait sérialiser le comparateur:

info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<tkey>)); 

Puis, dans la mise en œuvre de IDeserializationCallback.OnDeserialization il récupère la comparer:

comparer = (IEqualityComparer<tkey>)m_siInfo.GetValue(ComparerName, typeof(IEqualityComparer<tkey>)); 

Les classes implémentant l'interface IDeserializationCallback spécifient une méthode qui doit être exécutée après la désérialisation d'une instance, mais avant son renvoi à votre code.

Ref: Dictionary.cs méthodes GetObjectData et OnDeserialization

Questions connexes