2012-07-18 18 views
21

Tengo una clase Thing que se puede convertir implícitamente de string. Cuando llamo a un método con un parámetro Thing directamente, la conversión de string a Thing se realiza correctamente.Cómo realizar implícitamente una llamada a un método reflejado

Sin embargo si uso reflexión para llamar al mismo método que produce la excepción

System.ArgumentException : Object of type 'System.String' cannot be 
converted to type 'Things.Program+Thing'. 

tal vez hay una buena razón para esto, pero no puedo entenderlo. ¿Alguien tiene una idea de cómo hacer que esto funcione usando la reflexión?

namespace Things 
{ 
    class Program 
    { 
     public class Thing 
     { 
      public string Some; 

      public static implicit operator Thing(string s) 
      { 
       return new Thing {Some = s}; 
      } 
     } 

     public void showThing(Thing t) 
     { 
      Console.WriteLine("Some = " + t.Some); 
     } 

     public void Main() 
     { 
      showThing("foo"); 
      MethodInfo showThingReflected = GetType().GetMethod("showThing"); 
      showThingReflected.Invoke(this, new dynamic[] {"foo"}); 
     } 
    } 
} 

Meta: Por favor, no hay por qué las discusiones de fundición o de reflexión implícita es malo.

+4

De la parte superior de mi cabeza, yo apostaría que es porque (creo, y corríjanme si me equivoco) que la conversión implícita es la sintaxis de azúcar para el compilador. Que las llamadas reales al método de conversión estén conectadas en tiempo de compilación. EDITAR: ¿Necesita tener alguna forma genérica de invocar el convertidor implícito para cualquier conversión de objeto? ¿O es este un caso especial en el que estarías dispuesto a apuntar a un método estático separado o alguna otra llamada de reflexión a un método predeterminado o quizás a un constructor especializado? –

+0

pregunta similar [aquí] (http://stackoverflow.com/questions/4501469/c-sharp-implicit-cast-overloading-and-reflection-problem) –

+2

La fusión implícita es imposible a través de la reflexión, pero puede usar [TypeConvertor] (http://msdn.microsoft.com/en-us/library/98bbex99.aspx#the_typeconverter_class). –

Respuesta

1

En este caso específico se puede hacer la conversión a través del tipo de matriz, es decir

showThingReflected.Invoke(this, new Thing[] {"foo"}); 

pero eso es una especie de "trampa". En general, no puede esperar que el Invoke tenga en cuenta su implicit operator definido por el usuario. Esta conversión debe deducirse en tiempo de compilación.

9

El truco es darse cuenta de que el compilador crea un método estático especial llamado op_Implicit para su operador de conversión implícita.

object arg = "foo"; 

// Program.showThing(Thing t) 
var showThingReflected = GetType().GetMethod("showThing"); 

// typeof(Thing) 
var paramType = showThingReflected.GetParameters() 
            .Single() 
            .ParameterType; 

// Thing.implicit operator Thing(string s) 
var converter = paramType.GetMethod("op_Implicit", new[] { arg.GetType() }); 

if (converter != null) 
    arg = converter.Invoke(null, new[] { arg }); // Converter exists: arg = (Thing)"foo"; 

// showThing(arg) 
showThingReflected.Invoke(this, new[] { arg }); 
+0

brilliant !!!!!!!!!!!!! – denfromufa

+0

aquí hay otra respuesta similar: http://stackoverflow.com/a/32025393/2230844 – denfromufa

Cuestiones relacionadas