2012-07-20 13 views
19

¿Cómo convierto un objeto dinámico en Dictionary<TKey, TValue> en C# ¿Qué puedo hacer?Cómo convertir objetos a Dictionary <TKey, TValue> en C#?

public static void MyMethod(object obj) 
{ 
    if (typeof(IDictionary).IsAssignableFrom(obj.GetType())) 
    { 
     // My object is a dictionary, casting the object: 
     // (Dictionary<string, string>) obj; 
     // causes error ... 
    } 
    else 
    { 
     // My object is not a dictionary 
    } 
} 
+0

Se comprueba que su objeto es una 'IDictionary'. Entonces lanzar a esa interfaz, como '(IDictionary) obj', tendrá éxito. Sin embargo, hay muchos otros 'Idictionary' que' Dictionary '. Por lo tanto, es mejor que pruebe el mismo tipo al que desea lanzar. Estoy de acuerdo con Nikhil (que responde) que quiere usar 'como 'en este caso. Puedo proporcionar detalles si es necesario. –

+0

En general, considere las respuestas aquí: http://stackoverflow.com/questions/3481923/in-c-sharp-convert-anonymous-type-into-key-value-array (por ejemplo, 'RouteValueDictionary') –

Respuesta

16
public static KeyValuePair<object, object > Cast<K, V>(this KeyValuePair<K, V> kvp) 
    { 
     return new KeyValuePair<object, object>(kvp.Key, kvp.Value); 
    } 

    public static KeyValuePair<T, V> CastFrom<T, V>(Object obj) 
    { 
     return (KeyValuePair<T, V>) obj; 
    } 

    public static KeyValuePair<object , object > CastFrom(Object obj) 
    { 
     var type = obj.GetType(); 
     if (type.IsGenericType) 
     { 
      if (type == typeof (KeyValuePair<,>)) 
      { 
       var key = type.GetProperty("Key"); 
       var value = type.GetProperty("Value"); 
       var keyObj = key.GetValue(obj, null); 
       var valueObj = value.GetValue(obj, null); 
       return new KeyValuePair<object, object>(keyObj, valueObj); 
      } 
     } 
     throw new ArgumentException(" ### -> public static KeyValuePair<object , object > CastFrom(Object obj) : Error : obj argument must be KeyValuePair<,>"); 
    } 

Desde el OP:

En lugar de convertir mi diccionario completo, decidí mantener mi obj dinámico todo el tiempo. Cuando accedo a las claves y valores de mi diccionario con un foreach posterior, utilizo foreach (clave dinámica en obj.Keys) y convierto las claves y valores a cadenas simplemente.

4

esto debería funcionar:

para números, cadenas, fecha, etc .:

public static void MyMethod(object obj) 
    { 
     if (typeof(IDictionary).IsAssignableFrom(obj.GetType())) 
     { 
      IDictionary idict = (IDictionary)obj; 

      Dictionary<string, string> newDict = new Dictionary<string, string>(); 
      foreach (object key in idict.Keys) 
      { 
       newDict.Add(key.ToString(), idict[key].ToString()); 
      } 
     } 
     else 
     { 
      // My object is not a dictionary 
     } 
    } 

si su diccionario también contiene algunos otros objetos:

public static void MyMethod(object obj) 
    { 
     if (typeof(IDictionary).IsAssignableFrom(obj.GetType())) 
     { 
      IDictionary idict = (IDictionary)obj; 
      Dictionary<string, string> newDict = new Dictionary<string, string>(); 

      foreach (object key in idict.Keys) 
      { 
       newDict.Add(objToString(key), objToString(idict[key])); 
      } 
     } 
     else 
     { 
      // My object is not a dictionary 
     } 
    } 

    private static string objToString(object obj) 
    { 
     string str = ""; 
     if (obj.GetType().FullName == "System.String") 
     { 
      str = (string)obj; 
     } 
     else if (obj.GetType().FullName == "test.Testclass") 
     { 
      TestClass c = (TestClass)obj; 
      str = c.Info; 
     } 
     return str; 
    } 
+0

myTypes [0] y myTypes [1] siempre será System.Object. Ayudaría mucho seguir los tipos de mi diccionario, pero parece que no funciona. incluso necesito convertir el diccionario a al final, sin embargo thx. – modiX

+0

fue mi culpa, para obtener los tipos que tienes que hacer con idictionary 'IDictionary idict = (IDictionary) obj; Tipo [] myTypes = idict.GetType(). GetGenericArguments(); Diccionario dict = idict.Cast () .ToDictionary (entry => entry.Key, entry => entry.Value); ' – user1519979

+0

tengo updatet en mi publicación, tal vez me ayude – user1519979

-1

Mientras Comprenda que no está seguro de cuáles son las claves y los valores, pero desea convertirlos en cadenas.

Tal vez esto puede funcionar:

public static void MyMethod(object obj) 
{ 
    var iDict = obj as IDictionary; 
    if (iDict != null) 
    { 
    var dictStrStr = iDict.Cast<DictionaryEntry>() 
     .ToDictionary(de => de.Key.ToString(), de => de.Value.ToString()); 

    // use your dictStrStr   
    } 
    else 
    { 
    // My object is not an IDictionary 
    } 
} 
+0

recibe una excepción de conversión inválida si obj es un diccionario (no contiene ninguna clave o valores nulos). parece que tiene problemas para convertir el número en una cadena. – modiX

+0

incluso arroja una excepción de conversión no válida, si entrego un diccionario en esa línea. Sin embargo, gracias a la sugerencia, podría estar cerca de mi solución. – modiX

+0

Hmm, también es una solución fea. ¿De dónde viene 'obj'? Si supiéramos que siempre fue un 'Dictionary <,>' de algún tipo, podríamos hacer 'MyMethod' genérico, y todo sería simple y hermoso. El problema con 'IDictionary' es que también podría ser un' Hashtable' o muchos otros tipos que no son genéricos. Y el tipo de objeto 'foreach' no es el mismo (la razón por la cual mi respuesta no funcionó). –

2

clave Suponiendo que sólo puede ser una cadena, pero el valor puede ser cualquier cosa probar este

public static Dictionary<TKey, TValue> MyMethod<TKey, TValue>(object obj) 
{ 
    var stringDictionary = obj as Dictionary<TKey, TValue>; 

    if (stringDictionary!= null) 
    { 
     return stringDictionary; 
    } 
    var baseDictionary = obj as IDictionary; 

    if (baseDictionary != null) 
    { 
     var dictionary = new Dictionary<TKey, TValue>(); 
     foreach (DictionaryEntry keyValue in baseDictionary) 
     { 
      if (!(keyValue.Value is TValue)) 
      { 
       // value is not TKey. perhaps throw an exception 
       return null; 
      } 
      if (!(keyValue.Key is TKey)) 
      { 
       // value is not TValue. perhaps throw an exception 
       return null; 
      } 

      dictionary.Add((TKey)keyValue.Key, (TValue)keyValue.Value); 
     } 
     return dictionary; 
    } 
    // object is not a dictionary. perhaps throw an exception 
    return null; 

} 
29

utilizo este helper:

public static class ObjectToDictionaryHelper 
{ 
    public static IDictionary<string, object> ToDictionary(this object source) 
    { 
     return source.ToDictionary<object>(); 
    } 

    public static IDictionary<string, T> ToDictionary<T>(this object source) 
    { 
     if (source == null) 
      ThrowExceptionWhenSourceArgumentIsNull(); 

     var dictionary = new Dictionary<string, T>(); 
     foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(source)) 
      AddPropertyToDictionary<T>(property, source, dictionary); 
     return dictionary; 
    } 

    private static void AddPropertyToDictionary<T>(PropertyDescriptor property, object source, Dictionary<string, T> dictionary) 
    { 
     object value = property.GetValue(source); 
     if (IsOfType<T>(value)) 
      dictionary.Add(property.Name, (T)value); 
    } 

    private static bool IsOfType<T>(object value) 
    { 
     return value is T; 
    } 

    private static void ThrowExceptionWhenSourceArgumentIsNull() 
    { 
     throw new ArgumentNullException("source", "Unable to convert object to a dictionary. The source object is null."); 
    } 
} 

el uso es sólo para llamar .ToDictionary() en un objeto

espero que ayude.

-1
object parsedData = se.Deserialize(reader); 
System.Collections.IEnumerable stksEnum = parsedData as System.Collections.IEnumerable; 

¡entonces podrá enumerarlo!

2
public static void MyMethod(object obj){ 
    Dictionary<string, string> dicEditdata = data as Dictionary<string, string>; 
    string abc=dicEditdata["id"].ToString();} 

suponen --- si coloca el cursor sobre el objeto (obj), mientras que la depuración y si se obtiene un objeto con el valor {['id':'ID1003']} continuación, puede utilizar el valor como

string abc=dicEditdata["id"].ToString(); 
-1

manera simple:

public IDictionary<T, V> toDictionary<T, V>(Object objAttached) 
{ 
    var dicCurrent = new Dictionary<T, V>(); 
    foreach (DictionaryEntry dicData in (objAttached as IDictionary)) 
    { 
     dicCurrent.Add((T)dicData.Key, (V)dicData.Value); 
    } 
    return dicCurrent; 
} 
+0

La pregunta no es "¿Cómo convertir objetos IDictionary a IDictionary ?". La pregunta es "Cómo convertir objetos Object a IDictionary ?". – dizel3d

0

se puede crear un método de extensión genérico y luego usarlo en el objeto como:

public static class Extensions 
{ 
    public static KeyValuePair<TKey, TValue> ToKeyValuePair<TKey, TValue>(this Object obj) 
    { 
     // if obj is null throws exception 
     Contract.Requires(obj != null); 

     // gets the type of the obj parameter 
     var type = obj.GetType(); 
     // checks if obj is of type KeyValuePair 
     if (type.IsGenericType && type == typeof(KeyValuePair<TKey, TValue>)) 
     { 

      return new KeyValuePair<TKey, TValue>(
                (TKey)type.GetProperty("Key").GetValue(obj, null), 
                (TValue)type.GetProperty("Value").GetValue(obj, null) 
               ); 

     } 
     // if obj type does not match KeyValuePair throw exception 
     throw new ArgumentException($"obj argument must be of type KeyValuePair<{typeof(TKey).FullName},{typeof(TValue).FullName}>"); 
} 

y su uso sería como:

KeyValuePair<string,long> kvp = obj.ToKeyValuePair<string,long>(); 
3

Las respuestas anteriores son todo fresco. Encontré fácil serializar el objeto y deserializarlo como un diccionario.

var json = JsonConvert.SerializeObject(obj); 
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(json); 

No sé cómo se realiza el rendimiento, pero esto es mucho más fácil de leer. También podría envolverlo dentro de una función.

public static Dictionary<string, TValue> ToDictionary<TValue>(object obj) 
{  
    var json = JsonConvert.SerializeObject(obj); 
    var dictionary = JsonConvert.DeserializeObject<Dictionary<string, TValue>>(json); 
    return dictionary; 
} 

uso de este modo:

var obj = new { foo = 12345, boo = true }; 
var dictionary = ToDictionary<string>(obj); 
0

utilizo este método simple:

public Dictionary<string, string> objToDict(XYZ.ObjectCollection objs) { 
    var dict = new Dictionary<string, string>(); 
    foreach (KeyValuePair<string, string> each in objs){ 
     dict.Add(each.Key, each.Value); 
    } 
    return dict; 
} 
Cuestiones relacionadas