2015-07-10 15 views
7

Supponiamo Ho le seguenti dizionari:operazioni LINQ su IDictionary

private Dictionary<int, string> dic1 = new Dictionary<int, string>() 
{ 
     { 1, "a" }, 
     { 2, "b" }, 
     { 3, "c" } 
} 

private Dictionary<SomeEnum, bool> dic2 = new Dictionary<SomeEnum, bool>() 
{ 
     { SomeEnum.First, true }, 
     { SomeEnum.Second, false }, 
     { SomeEnum.Third, false } 
} 

voglio convertire questi due dizionari in un Dictionary<string, object>

Ad esempio:

dic1 = new Dictionary<string, object>() 
{ 
    { "1", "a" }, 
    { "2", "b" }, 
    { "3", "c" } 
} 

dic2 = new Dictionary<string, object>() 
{ 
    { "First", true }, 
    { "Second", false }, 
    { "Third", false } 
} 

Come si può vedere , la chiave string di questi dizionari è solo la rappresentazione string di quelli precedenti.

Il metodo che è responsabile per la conversione ha la seguente firma:

public static object MapToValidType(Type type, object value) 
{ 
    //.... 

    if(typeof(IDictionary).IsAssignableFrom(type)) 
    { 
     //I have to return a Dictionary<string, object> here 
     return ??; 
    } 
} 

Ho provato quanto segue:

((IDictionary)value).Cast<object>().ToDictionary(i => ...); 

Ma i stata fusa a un oggetto, quindi non posso accedere al chiave o valore. Per questo avrei dovuto lanciarlo nell'approciato KeyValuePair<TKey, TValue>, ma non conosco il tipo TKey o TValue.

Un'altra soluzione è quella di fare questo:

IDictionary dic = (IDictionary)value; 
IList<string> keys = dic.Keys.Cast<object>().Select(k => Convert.ToString(k)).ToList(); 
IList<object> values = dic.Values.Cast<object>().ToList(); 
Dictionary<string, object> newDic = new Dictionary<string, object>(); 
for(int i = 0; i < keys.Count; i++) 
    newDic.Add(keys[0], values[0]); 
return newDic; 

Tuttavia, io non sono un gran fan di questo approccio e non vedo per una sola riga dichiarazione LINQ più semplice e più amichevole.

+0

Dai un'occhiata alla mia risposta è che ciò che è necessario, convertire qualsiasi dizionario generico Dictionary , semplici due operazioni, una riga, il metodo – BhavO

risposta

1

si può provare questo, non LINQ però, credo che non hai bisogno di:

Dictionary<string, object> ConvertToDictionary(System.Collections.IDictionary iDic) { 
      var dic = new Dictionary<string, object>(); 
      var enumerator = iDic.GetEnumerator(); 
      while (enumerator.MoveNext()) { 
       dic[enumerator.Key.ToString()] = enumerator.Value; 
      } 
     return dic; 
    } 

Or uno Linq:

return iDic.Keys.Cast<object>().ToDictionary(k=> k.ToString(), v=> iDic[v]); 
+0

Più semplice del mio approccio, ma non devo perdere la speranza per un'alternativa LINQ –

+0

Ok, ora ne metto uno :) – George

+0

Cammino! Quella singola linea LINQ funzionava come previsto! –

1
static void Main(string[] args) 
    { 
     var blah = KeyToString(dic1); 

     // Verify that we converted correctly 
     foreach (var kvp in blah) 
     { 
      Console.WriteLine("{0} {1}, {2} {3}", kvp.Key.GetType(), kvp.Key, kvp.Value.GetType(), kvp.Value); 
     } 
    } 

    static Dictionary<string, TValue> KeyToString<TKey, TValue>(IEnumerable<KeyValuePair<TKey, TValue>> dic1) 
    { 
     return dic1.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value); 
    } 
+1

sto lavorando con 'IDictionary', come posso usa il tuo metodo? –

+0

Modificato per usare più generale 'IEnumerable >', che 'IDictionary ' implementa –

+1

Probabilmente ti ho confuso. Sto usando [IDictionary] (https://msdn.microsoft.com/en-us/library/system.collections.idictionary%28v=vs.110%29.aspx) senza generici. [IDictionary ] (https://msdn.microsoft.com/en-us/library/s4ys34ea%28v=vs.110%29.aspx) è un altro tipo –

0
public static IDictionary<string, object> Convert<TKey, TValue>(IDictionary<TKey, TValue> genDictionary) 
{ 
    return genDictionary.Select(kvp => new KeyValuePair<string, object>(kvp.Key.ToString(), (object)kvp.Value)).ToDictionary(x => x.Key, x => x.Value); 
} 

chiamato come:

var dicIntInt = new Dictionary<int, string>{{123, "asdc"}, {456, "aa"} }; 

    Dictionary<string, object> dicStrObj = Convert(dicIntInt); 

https://dotnetfiddle.net/eY41MQ

+0

Vorrei che fosse così facile, ma 'd1' è di tipo 'IDictionary' nel mio caso, quindi non posso applicare query LINQ su di esso –

+0

aggiornato, funziona come un fascino – BhavO

+0

Sto lavorando con' IDictionary '(non generico), ma il tuo metodo' Convert' prende un 'dizionario ' che è una classe completamente diversa (e usa i generici) –

-1

Il trucco consiste nel trasmettere il tuo IDictionary a un tipo generico di DictionaryEntry. Quindi è possibile utilizzare ToDictionary() da System.Linq.

static Dictionary<string,object> ToDictionary(IDictionary dic) 
{ 
    return dic.Cast<DictionaryEntry>().ToDictionary ((t) => t.Key.ToString(), (t) => t.Value); 
}