既存のNameValueCollectionオブジェクトから辞書に値をコピーしようとしています。私はそれを行うために以下のコードを持っていますが、Addは私のキーと値が文字列であることを受け入れないようです
IDictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
public void copyFromNameValueCollection (NameValueCollection a)
{
foreach (var k in a.AllKeys)
{
dict.Add(k, a[k]);
}
}
注: NameValueCollectionにはStringキーと値が含まれているため、ここでそれらをgeneric辞書にコピーできるメソッドを提供したいだけです。
string
sを任意のジェネリック型に割り当てることができないため、ここでジェネリックを使用する意味はありません。
IDictionary<string, string> dict = new Dictionary<string, string>();
public void copyFrom(NameValueCollection a)
{
foreach (var k in a.AllKeys)
{
dict.Add(k, a[k]);
}
}
ただし、代わりに新しい辞書を作成するメソッドを作成する必要があります。
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;
}
次のように使用できます:
NameValueCollection nvc = //
var dictionary = nvc.ToDictionary();
コレクション内の文字列を必要なキー/値型に変換する一般的な方法が必要な場合は、型コンバーターを使用できます。
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;
}
拡張メソッドと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]);
LINQを使用します。
public static IDictionary<string, string> ToDictionary(this NameValueCollection collection)
{
return collection.Cast<string>().ToDictionary(k => k, v => collection[v]);
}
使用法:
IDictionary<string, string> dic = nv.ToDictionary();
スーパーショートバージョン
var dataNvc = HttpUtility.ParseQueryString(data);
var dataCollection = dataNvc.AllKeys.ToDictionary(o => o, o => dataNvc[o]);
辞書に常に文字列が含まれることがわかっている場合は、クラスをジェネリックにする代わりに、文字列を含むように辞書を指定します。
IDictionary<string, string> dict = new Dictionary<string, string>();
これにより、物事は(一般的なメソッド仕様がなくても)書かれているように「機能する」だけです。
これをジェネリッククラスにする必要があり、ジェネリックデータを保持する場合は、string
からTKey
およびstring
からTValue
に変換する方法が必要です。これを行うには、コピーメソッドにデリゲートを提供できます。
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]));
}
}
次に、文字列からTValue
への変換と文字列からTKey
への変換を実行するデリゲートを渡す必要があります。
EqualityComparerを忘れないでください。しかし、それは公有財産ではありません。したがって、リフレクションを使用して取得する必要があります。
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;
}