2011-01-19 11 views
14

Tengo algunos problemas para invocar un método estático sobrecargado con un parámetro de salida por reflexión y agradecería algunos indicadores.Reflexión sobre un método estático sobrecargado usando un parámetro de salida

Estoy buscando crear dinámicamente un tipo como System.Int32 o System.Decimal, y luego invocar el método estático TryParse(string, out x) en él.

El código de abajo tiene dos problemas:

  • t.GetMethod("TryParse", new Type[] { typeof(string), t }) no puede devolver el MethodInfo espero

  • mi.Invoke(null, new object[] { value.ToString(), concreteInstance }) parece tener éxito, pero no establece el parámetro a cabo concreteInstance al valor analizado

Entretejido en esta función se puede ver un código temporal que demuestra lo que debería suceder si el parámetro type se configuró en System.Decimal.

public static object Cast(object value, string type) 
{ 
    Type t = Type.GetType(type); 
    if (t != null) 
    { 
     object concreteInstance = Activator.CreateInstance(t); 
     decimal tempInstance = 0; 

     List<MethodInfo> l = new List<MethodInfo>(t.GetMethods(BindingFlags.Static | BindingFlags.Public)); 

     MethodInfo mi; 
     mi = t.GetMethod("TryParse", new Type[] { typeof(string), t }); //this FAILS to get the method, returns null 
     mi = l.FirstOrDefault(x => x.Name == "TryParse" && x.GetParameters().Length == 2); //ugly hack required because the previous line failed 
     if (mi != null) 
     { 
      try 
      { 
       bool retVal = decimal.TryParse(value.ToString(), out tempInstance); 
       Console.WriteLine(retVal.ToString());  //retVal is true, tempInstance is correctly set 
       object z = mi.Invoke(null, new object[] { value.ToString(), concreteInstance }); 
       Console.WriteLine(z.ToString());   //z is true, but concreteInstance is NOT set 
      } 
      catch (Exception ex) 
      { 
       Debug.WriteLine(ex.Message); 
      } 
     } 

     return concreteInstance; 
    } 

    return value; 
} 

¿Qué necesito hacer para asegurarse de que mi t.GetMethod() llamada devuelve el MethodInfo correcta? ¿Qué debo hacer para tener el concreteInstance configurado correctamente en mi llamada mi.Invoke()?

Sé que hay un montón de preguntas sobre este tema, pero la mayoría de ellas involucran métodos estáticos genéricos o métodos estáticos que no están sobrecargados. This question es similar, pero no es un duplicado.

Respuesta

26

Debe usar el BindingFlags derecho y usar Type.MakeByRefType para los parámetros out y ref. Un segundo, y tendré una muestra de código para ti.

Por ejemplo,

MethodInfo methodInfo = typeof(int).GetMethod(
    "TryParse", 
    BindingFlags.Public | BindingFlags.Static, 
    Type.DefaultBinder, 
    new[] { typeof(string), typeof(int).MakeByRefType() }, 
    null 
); 

Debo señalar que la invocación de esto es un poco difícil también. Así es como lo haces.

string s = "123"; 
var inputParameters = new object[] { "123", null }; 
methodInfo.Invoke(null, inputParameters); 
Console.WriteLine((int)inputParameters[1]); 

La primera null es porque estamos invocando un método estático (no hay ningún objeto "receptor" esta invocación). El null en inputParameters nos será "rellenado" por TryParse con el resultado del análisis (es el parámetro out).

+0

Excelente respuesta, gracias @Jason. – slugster

Cuestiones relacionadas