2011-01-12 10 views
60

Tengo una lista de tipos (System.Type) que necesitan ser consultados en la base de datos.C# use System.Type como parámetro genérico

Para cada uno de estos tipos, tengo que llamar al siguiente extensionmethod (que es parte de LinqToNhibernate):

Session.Linq<MyType>() 

sin embargo no tienen MyType, pero quiero utilizar un tipo de lugar.

Lo que tengo es:

System.Type typeOne; 

pero no puedo realizar lo siguiente:

Session.Linq<typeOne>() 

¿Cómo puedo utilizar un tipo como un parámetro genérico?

Respuesta

70

No se puede, directamente. El objetivo de los genéricos es proporcionar en tiempo de compilación tipo de seguridad, donde conoce el tipo que le interesa en tiempo de compilación, y puede trabajar con instancias de ese tipo. En su caso, solo conoce el Type por lo que no puede obtener comprobaciones en tiempo de compilación de que los objetos que tenga sean instancias de ese tipo.

Tendrá que llamar al método a través de la reflexión - algo como esto:

// Get the generic type definition 
MethodInfo method = typeof(Session).GetMethod("Linq", 
           BindingFlags.Public | BindingFlags.Static); 

// Build a method with the specific type argument you're interested in 
method = method.MakeGenericMethod(typeOne); 
// The "null" is because it's a static method 
method.Invoke(null, arguments); 

Si es necesario utilizar este tipo mucho, puede que le resulte más conveniente para escribir su propio método genérico que llama cualesquiera otros métodos genéricos que necesite, y luego llame al con método con reflexión.

+1

Leí sobre una solución que utiliza la reflexión para llamar al método. Pero esperaba que hubiera otra solución. – Jan

+2

@Jan nope; eso es todo –

+0

el método invoke devuelve un "Objeto". No puedo consultar sobre este objeto hasta que lo copie al Tipo correcto. (Que probablemente sería IQueryable ). ¿Cómo puedo lanzar el objeto al tipo que tengo? – Jan

22

Para ello, tiene que utilizar la reflexión:

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null); 

(suponiendo que Linq<T>() es un método estático del tipo Session)

Si Session es en realidad un objeto , necesitará saber dónde se declara realmente el método Linq, y pasar Session como argumento:

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne) 
    .Invoke(null, new object[] {Session}); 
Cuestiones relacionadas