2011-09-14 17 views
17

Come utilizzeresti il ​​reflection per eseguire il metodo seguente quando il tipo può essere dedotto solo in fase di esecuzione?Come attivare un metodo generico che accetta un'azione come parametro

MainObject.TheMethod<T>(Action<OtherObject<T>>) 

nell'uso quotidiano, in genere:

mainObject.Method<Message>(m => m.Do("Something")) 

Quindi, data una lista di tipi, ho bisogno di sostituirli per T nel metodo di cui sopra e invocare.

Questo è dove ho ottenuto prima della mia testa ai rivolta a stucco:

var mapped = typeof(Action<OtherObject<>>).MakeGenericType(t.GetType()); 
Activator.CreateInstance(mapped, new object[] { erm do something?}); 

typeof(OtherObject) 
    .GetMethod("TheMethod") 
    .MakeGenericMethod(t.GetType()) 
    .Invoke(model, new object[] { new mapped(m => m.Do("Something")) }); 

Update: Per chiarimenti, ho una lista di tipi e mi auguro di eseguire lo stesso metodo conosciuto di otherObject per ogni . Pseudo-codice:

foreach(var t in types) 
{ 
    mainObject.TheMethod<t>(mo => mo.Do("Something")) 
} 

(Il tipo di parametro per TheMethod() è Action<OtherObject<T>> come indicato sopra)

FluentNHibernate.Automapping.AutoPersistenceModel Override<T>(System.Action<AutoMapping<T>> populateMap) 

dell'azione è lo stesso di AutoMapping<T>.Where("something")

model.Override<Message>(m => m.Where("DeletedById is null")) 

Ora, fallo per un sacco di tipi :)

+2

è il corpo dell'azione sempre lo stesso, vale a dire sempre m.Do '("Something")'? –

+0

sì, è stato aggiunto qualche chiarimento sopra –

+0

La risposta non ti è di aiuto? –

risposta

3

Puoi risolvere questo problema utilizzando le espressioni:

foreach(var t in types) 
{ 
    var mapped = typeof(AutoMapping<>).MakeGenericType(t); 

    var p = Expression.Parameter(mapped, "m"); 
    var expression = Expression.Lambda(Expression.GetActionType(mapped), 
             Expression.Call(p, mapped.GetMethod("Do"), 
             Expression.Constant("Something")), p); 

    typeof(SomeOtherObject).GetMethod("TheMethod").MakeGenericMethod(t) 
          .Invoke(model, new object[] { expression.Compile() }); 
} 

UPDATE: esempio di lavoro completo (incollare in LINQPad ed eseguirlo):

void Main() 
{ 
    var types = new []{typeof(string), typeof(Guid)}; 
    SomeOtherObject model = new SomeOtherObject(); 
    foreach(var t in types) 
    { 
     var mapped = typeof(AutoMapping<>).MakeGenericType(t); 

     var p = Expression.Parameter(mapped, "m"); 
     var expression = Expression.Lambda(
          Expression.GetActionType(mapped), 
          Expression.Call(p, mapped.GetMethod("Do"), 
          Expression.Constant("Something")), p); 

     typeof(SomeOtherObject).GetMethod("TheMethod") 
           .MakeGenericMethod(t) 
           .Invoke(model, 
             new object[] { expression.Compile() }); 
    } 
} 

class AutoMapping<T> 
{ 
    public void Do(string p) 
    { 
     Console.WriteLine(typeof(T).ToString()); 
     Console.WriteLine(p); 
    } 
} 

class SomeOtherObject 
{ 
    public void TheMethod<T>(Action<AutoMapping<T>> action) 
    { 
     var x = new AutoMapping<T>(); 
     action(x); 
    } 
} 
+0

Ci scusiamo per la risposta in ritardo. Hanno messo questo in atto. Sto ottenendo il tipo previsto su questo: var mapped = typeof (Action >). MakeGenericType (t); –

+0

Quale versione .NET stai usando? E puoi per favore darmi il messaggio di errore completo? Presumo che questo sia un errore di compilazione? –

+0

@BobTodd: si prega di consultare il codice aggiornato. Prova questo. –

Problemi correlati