web-dev-qa-db-fra.com

Copier les valeurs de clé de NameValueCollection dans le dictionnaire générique

Essayer de copier les valeurs d'un objet NameValueCollection existant dans un dictionnaire. J'ai le code suivant ci-dessous pour le faire, mais apparemment, Add n'accepte pas que mes clés et mes valeurs soient en tant que chaînes. 

IDictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
public void copyFromNameValueCollection (NameValueCollection a)
{
    foreach (var k in a.AllKeys)
    { 
        dict.Add(k, a[k]);
    }  
}

Remarque: NameValueCollection contient des clés et des valeurs de chaîne. Par conséquent, je souhaite simplement fournir ici une méthode permettant de les copier dans un dictionnaire generic .

24
Kobojunkie

Cela n'a aucun sens d'utiliser les génériques ici, car vous ne pouvez pas affecter strings à un type générique arbitraire:

IDictionary<string, string> dict = new Dictionary<string, string>();

public void copyFrom(NameValueCollection a)
{
            foreach (var k in a.AllKeys)
            { 
                dict.Add(k, a[k]);
            }  
}

bien que vous deviez probablement créer une méthode pour créer un nouveau dictionnaire:

public static IDictionary<string, string> ToDictionary(this NameValueCollection col)
{
    IDictionary<string, string> dict = new Dictionary<string, string>();
    foreach (var k in col.AllKeys)
    { 
        dict.Add(k, col[k]);
    }  
    return dict;
}

que vous pouvez utiliser comme:

NameValueCollection nvc = //
var dictionary = nvc.ToDictionary();

Si vous voulez un moyen général de convertir les chaînes de la collection en types clé/valeur requis, vous pouvez utiliser des convertisseurs de type:

public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this NameValueCollection col)
{
    var dict = new Dictionary<TKey, TValue>();
    var keyConverter = TypeDescriptor.GetConverter(typeof(TKey));
    var valueConverter = TypeDescriptor.GetConverter(typeof(TValue));

    foreach(string name in col)
    {
        TKey key = (TKey)keyConverter.ConvertFromString(name);
        TValue value = (TValue)valueConverter.ConvertFromString(col[name]);
        dict.Add(key, value);
    }

    return dict;
}
31
Lee

Méthode d'extension plus linq:

 public static Dictionary<string, string> ToDictionary(this NameValueCollection nvc) {
    return nvc.AllKeys.ToDictionary(k => k, k => nvc[k]);
 }

 //example
 var dictionary = nvc.ToDictionary();
54
katbyte
parameters.AllKeys.ToDictionary(t => t, t => parameters[t]);
13
Chobits

Utilisez LINQ:

public static IDictionary<string, string> ToDictionary(this NameValueCollection collection)
{
    return collection.Cast<string>().ToDictionary(k => k, v => collection[v]);
}

Usage:

IDictionary<string, string> dic = nv.ToDictionary();
4
abatishchev

Version très courte

var dataNvc = HttpUtility.ParseQueryString(data);
var dataCollection = dataNvc.AllKeys.ToDictionary(o => o, o => dataNvc[o]);
2
1232133d2ffa

Si vous savez que votre dictionnaire contiendra toujours des chaînes, spécifiez-le pour contenir des chaînes au lieu de rendre votre classe générique:

IDictionary<string, string> dict = new Dictionary<string, string>();

Avec cela, les choses "fonctionneront" telles que rédigées (sans la spécification de méthode générique).

Si vous souhaitez que cette classe soit générique et contienne des données génériques, vous avez besoin d'un moyen de convertir string en TKey et string en TValue. Vous pouvez fournir aux délégués votre méthode de copie pour ce faire:

public void CopyFrom(NameValueCollection a, Func<string, TKey> keyConvert, Func<string, TValue> valueConvert)
{
    foreach(var k in a.AllKeys)
    {
         dict.Add(keyConvert(k), valueConvert(a[k]));
    }
}

Vous devrez ensuite passer un délégué qui effectuera la conversion de chaîne en TValue et chaîne en TKey.

2
Reed Copsey

Vous ne devez pas oublier EqualityComparer. Mais ce n'est pas une propriété publique. Donc, vous devriez utiliser la réflexion pour l'obtenir.

public static IEqualityComparer GetEqualityComparer(this NameObjectCollectionBase nameObjectCollection)
  {
  PropertyInfo propertyInfo = typeof(NameObjectCollectionBase).GetProperty("Comparer", BindingFlags.Instance | BindingFlags.NonPublic);
  return (IEqualityComparer)propertyInfo.GetValue(nameObjectCollection);
  }

public static IEqualityComparer<string> GetEqualityComparer(this NameValueCollection nameValueCollection)
  {
  return (IEqualityComparer<string>)((NameObjectCollectionBase)nameValueCollection).GetEqualityComparer();
  }

public static Dictionary<string, string> ToDictionary(this NameValueCollection nameValueCollection)
  {
  Dictionary<string, string> dictionary =
    nameValueCollection.AllKeys.ToDictionary(x => x, x => nameValueCollection[x], nameValueCollection.GetEqualityComparer());
  return dictionary;
  }
0
Dmitriy Dokshin