C#使用System.Type作为通用参数

Jan*_*Jan 78 c# generics types .net-4.0

我有一个类型列表(System.Type),需要在数据库中查询.

对于每种类型,我需要调用以下extensionmethod(它是LinqToNhibernate的一部分):

Session.Linq<MyType>()
Run Code Online (Sandbox Code Playgroud)

但是我没有MyType,但我想使用Type.

我有的是:

System.Type typeOne;
Run Code Online (Sandbox Code Playgroud)

但我无法执行以下操作:

Session.Linq<typeOne>()
Run Code Online (Sandbox Code Playgroud)

如何使用Type作为通用参数?

Jon*_*eet 83

你不能,直接.泛型的要点是提供编译时类型安全性,您可以在编译时知道您感兴趣的类型,并且可以使用该类型的实例.在您的情况下,您只知道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);
Run Code Online (Sandbox Code Playgroud)

如果你需要经常使用这个类型,你可能会发现编写自己的泛型方法更方便,该方法调用它需要的任何其他泛型方法,然后用反射调用你的方法.

  • @Jan:你不能 - 但是你也不能使用那种类型,因为你不知道编译时的类型......这是值得你编写泛型方法的地方以强烈的方式完成你想要的一切,并用反射调用*that*.或者,非通用的`IQueryable`能做你需要的吗? (3认同)
  • 我读到了一个使用反射来调用方法的解决方案。但我希望有另一种解决方案。 (2认同)
  • @Jan nope; 而已 (2认同)
  • @Jon:谢谢,我会尝试编写自己的通用方法.不幸的是,非泛型Iqueryable不会解决问题. (2认同)

Mar*_*ell 28

要做到这一点,你需要使用反射:

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);
Run Code Online (Sandbox Code Playgroud)

(假设这Linq<T>()是类型上的静态方法Session)

如果Session实际上是一个对象,您需要知道Linq方法实际声明的位置,并Session作为参数传入:

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});
Run Code Online (Sandbox Code Playgroud)