سؤال

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.

هل كانت مفيدة؟

المحلول 2

It doesn't make sense to use generics here since you can't assign strings 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;
}

نصائح أخرى

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

Super-Short Version

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

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.

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;
  }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top