2011-01-12 2 views
60

У меня есть список типов (System.Type), которые необходимо запросить в базе данных.C# use System.Type as Generic параметр

Для каждого из этих типов, я должен назвать следующий метод расширения (который является частью LinqToNhibernate):

Session.Linq<MyType>() 

Однако у меня нет MyType, но я хочу, чтобы использовать тип вместо.

Что у меня есть:

System.Type typeOne; 

Но я не могу выполнить следующие действия:

Session.Linq<typeOne>() 

Как я могу использовать тип в качестве родового параметра?

ответ

70

Вы не можете напрямую. Точкой дженериков является предоставление времени компиляции типа безопасности, где вы знаете тип, который вас интересует во время компиляции, и можете работать с экземплярами этого типа. В вашем случае вы знаете только Type, поэтому вы не можете получить какие-либо проверки времени компиляции, если у каких-либо объектов есть экземпляры этого типа.

Вам нужно вызвать метод с помощью отражения - что-то вроде этого:

// 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); 

Если вам нужно использовать этот тип много, вы можете найти его более удобным, чтобы написать свой собственный универсальный метод, который вызывает любые другие общие методы, которые ему нужны, а затем вызовите ваш метод с отражением.

+1

Я читал о решении, которое использует отражение для вызова метода. Но я надеялся, что есть еще одно решение. – Jan

+2

@Jan nope; вот он –

+0

метод invoke возвращает «Object». Я не могу запросить этот объект, пока я не применил его к правильному типу. (Вероятно, это будет IQueryable ). Как я могу применить объект к типу, который у меня есть? – Jan

22

Для этого вам нужно использовать отражение:

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

(при условии, что Linq<T>() является статическим методом по типу Session)

Если Session является на самом деле объект, вам нужно знать, где фактически объявлен метод Linq, и передать в Session в качестве аргумента:

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne) 
    .Invoke(null, new object[] {Session}); 
Смежные вопросы