2010-04-28 11 views
9

Actualmente estoy tratando de escribir un método Dump() de LinqPad equivalente a iin C# para mi propio amusment. Me estoy moviendo de Java a C# y esto es un ejercicio en lugar de un requisito comercial. Tengo casi todo funcionando a excepción de Dumping a Dictionary.C# Reflection - ¿Cómo puedo saber si el objeto o es de tipo KeyValuePair y luego lanzarlo?

El problema es que KeyValuePair es un tipo de valor. Para la mayoría de los demás tipos de valor, simplemente llamo al método ToString, pero esto es insuficiente ya que KeyValuePair puede contener Enumerables y otros objetos con métodos ToString no deseados. Entonces necesito averiguar si es un KeyValuePair y luego lanzarlo. En Java podría usar comodines genéricos para esto, pero no sé el equivalente en C#.

Su búsqueda, dado un objeto o, determina si es un KeyValuePair y llama a Print en su clave y valor.

Print(object o) { 
    ... 
} 

¡Gracias!

Respuesta

31

Si no conoce los tipos almacenados en la KeyValuePair es necesario ejercer un poco de código reflexión.

Echemos un vistazo a lo que se necesita:

En primer lugar, vamos a garantizar el valor no es null:

if (value != null) 
{ 

A continuación, vamos a garantizar el valor es genérico:

Type valueType = value.GetType(); 
    if (valueType.IsGenericType) 
    { 

Entonces , extraiga la definición de tipo genérico, que es KeyValuePair<,>:

 Type baseType = valueType.GetGenericTypeDefinition(); 
     if (baseType == typeof(KeyValuePair<,>)) 
     { 

A continuación, extraer los tipos de los valores en ella:

  Type[] argTypes = baseType.GetGenericArguments(); 

código final:

if (value != null) 
{ 
    Type valueType = value.GetType(); 
    if (valueType.IsGenericType) 
    { 
     Type baseType = valueType.GetGenericTypeDefinition(); 
     if (baseType == typeof(KeyValuePair<,>)) 
     { 
      Type[] argTypes = baseType.GetGenericArguments(); 
      // now process the values 
     } 
    } 
} 

Si usted ha descubierto que el objeto en efecto, contiene una KeyValuePair<TKey,TValue> se puede extraer la clave real y un valor como este:

object kvpKey = valueType.GetProperty("Key").GetValue(value, null); 
object kvpValue = valueType.GetProperty("Value").GetValue(value, null); 
+0

Estaba a punto de sugerir exactamente eso ... :) Buena respuesta – Tigraine

+0

Increíble respuesta, muchas gracias – Logan

+2

¿El uso de la reflexión aquí tendrá un gran impacto en el rendimiento? – JDandChips

0
+0

El enlace al idioma inglés es http://msdn.microsoft.com/library/scekt9xw(VS.80).aspx –

+1

Creo que esto se vuelve problemático con los genéricos. Dado que KeyValuePair no es lo mismo que KeyValuePair .. Y en realidad no le importa de qué tipo es, siempre que haya un .ToString() en él ... (T: clase) – Tigraine

1

Presumiendo que está usando el KeyValuePair genérico entonces necesita probable que desee para comprobar si una instanciación particular, como una creada usando una cadena para ambos clave y el valor:

public void Print(object o) 
{ 
    if (o == null) 
     return; 

    if (o is KeyValuePair<string, string>) 
    { 
     KeyValuePair<string, string> pair = (KeyValuePair<string, string>)o; 
     Console.WriteLine("{0} = {1}", pair.Key, pair.Value); 
    } 
} 

Si desea probar para cualquier tipo de KeyValuePair continuación, tendrá que utilizar la reflexión. ¿Vos si?

Cuestiones relacionadas