简体   繁体   中英

Copy key values from NameValueCollection to Generic Dictionary

Trying to copy values from an existing NameValueCollection object to a Dictionary. I have the following code below to do that but seems the Add does not accept that my keys and values are as Strings

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

Note: NameValueCollection contains String keys and values and so I simply want to provide here a method to allow copying of those to a generic dictionary.

Extension method 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();

It doesn't make sense to use generics here since you can't assign string s to some arbitrary generic type:

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

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

although you should probably create a method to create a new dictionary instead:

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

which you can use like:

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

If you want a general way of converting the strings in the collection into the required key/value types, you can use type converters:

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;
}
parameters.AllKeys.ToDictionary(t => t, t => parameters[t]);

Use 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();

If you know that your dictionary is always going to contain strings, specify it to contain strings instead of making your class generic:

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

With this, things will "just work" as written (without the generic method specification).

If you need this to be a generic class, and hold generic data, you need some way to convert from string to TKey and string to TValue . You could provide delegates to your copy method to do this:

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

You would then need to pass a delegate in that would perform the conversion from string to TValue and string to TKey .

Super-Short Version

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

You should not forget about EqualityComparer. But it is not a public property. So, you should use reflection to get it.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM