2012-07-18 13 views
21

ho una classe Thing che è implicitamente calcinabile da un string. Quando chiamo un metodo con un Thing parametro direttamente il cast da string a Thing è fatto correttamente.come lanciare implicitamente su una chiamata di metodo riflessa

Tuttavia se uso riflessione di chiamare lo stesso metodo che genera l'eccezione

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

forse c'è una buona ragione per questo, ma non riesco a capirlo. Qualcuno ha un'idea di come farlo funzionare usando la riflessione?

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: Per favore, niente discussioni perché fusione implicita o di riflessione è male.

+4

Fuori della parte superiore della mia testa, io scommetterei che sia perché (penso, e mi corregga se sbaglio) che fusione implicita è la sintassi di zucchero per il compilatore. Che le chiamate effettive al metodo di casting siano cablate in fase di compilazione. EDIT: hai bisogno di un modo generico di invocare il convertitore implicito per qualsiasi conversione di oggetti? O si tratta di un caso speciale che vorresti indirizzare a un metodo statico separato o ad altre chiamate di riflessione su un metodo predeterminato o magari su un costruttore specializzato? –

+0

simile domanda [qui] (http://stackoverflow.com/questions/4501469/c-sharp-implicit-cast-overloading-and-reflection-problem) –

+2

cast implicito è impossibile attraverso la riflessione, ma è possibile usare [TypeConvertor] (http://msdn.microsoft.com/en-us/library/98bbex99.aspx#the_typeconverter_class). –

risposta

1

In questo caso specifico è possibile effettuare la conversione attraverso il tipo di matrice, cioè

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

ma questo è una sorta di "barare". In generale, non è possibile aspettarsi che lo Invoke consideri il proprio numero definito dall'utente implicit operator. Questa conversione deve essere dedotta in fase di compilazione.

9

Il trucco è quello di rendersi conto che il compilatore crea un metodo statico speciale chiamato op_Implicit per il vostro operatore di conversione implicita.

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

geniale !!!!!!!!!!!!! – denfromufa

+0

ecco un'altra risposta simile: http://stackoverflow.com/a/32025393/2230844 – denfromufa

Problemi correlati