2011-09-14 19 views
17

¿Cómo utilizaría la reflexión para ejecutar el siguiente método cuando el tipo solo se puede inferir en el tiempo de ejecución?Cómo activar un método genérico que toma una acción como su parámetro

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

en el uso diario, por lo general:

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

Así, dada una lista de tipos, que tienen que sustituirlos por T en el método anterior e invocar.

Esto es donde me dieron antes de la cabeza a recurrido a la masilla:

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")) }); 

Actualización: Para mayor claridad, tengo una lista de tipos y deseo de ejecutar el mismo método conocido de OtherObject para cada . Pseudo-código:

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

(El tipo del parámetro para TheMethod() es Action<OtherObject<T>> como se indicó anteriormente)

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

la acción es la misma de AutoMapping<T>.Where("something")

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

Ahora, hazlo por un montón de tipos :)

+2

es el cuerpo de la acción siempre el mismo, es decir, siempre 'm.Do ("Algo")'? –

+0

sí lo es, agregó alguna aclaración anterior –

+0

¿No te ayuda mi respuesta? –

Respuesta

3

Puedes resolver esto usando expresiones:

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() }); 
} 

ACTUALIZACIÓN: ejemplo de trabajo completa (pegarlo en LINQPad y ejecutarlo):

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

Lo siento por la respuesta tardía. Han puesto esto en su lugar. Obtengo el tipo esperado en esto: var mapped = typeof (Acción >). MakeGenericType (t); –

+0

¿Qué versión de .NET estás usando? ¿Y puede darme el mensaje de error completo? ¿Supongo que es un error de compilación? –

+0

@BobTodd: ver el código actualizado. Prueba esto. –

Cuestiones relacionadas