C#使用System.Type作为泛型参数

C#使用System.Type作为泛型参数,c#,generics,.net-4.0,types,C#,Generics,.net 4.0,Types,我有一个需要在数据库中查询的类型列表(System.Type) 对于每种类型,我都需要调用以下extensionmethod(它是LinqToNhibernate的一部分): 但我无法执行以下操作: Session.Linq<typeOne>() Session.Linq() 如何使用类型作为泛型参数?您不能直接使用。泛型的要点是提供编译时类型安全性,在编译时您知道您感兴趣的类型,并且可以使用该类型的实例。在您的例子中,您只知道类型,因此无法获得任何编译时检查,以确定您拥有的任何

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

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

但我无法执行以下操作:

Session.Linq<typeOne>()
Session.Linq()

如何使用类型作为泛型参数?

您不能直接使用。泛型的要点是提供编译时类型安全性,在编译时您知道您感兴趣的类型,并且可以使用该类型的实例。在您的例子中,您只知道
类型
,因此无法获得任何编译时检查,以确定您拥有的任何对象都是该类型的实例

您需要通过反射调用该方法-类似于以下内容:

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

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

为此,您需要使用反射:

typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);
(假设
Linq()
是类型
会话
上的静态方法)

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

typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});
我有一个通过反射调用泛型方法的通用方法

//
///此方法通过反射调用您的方法
///因此,我将通过反射(assemblyQualifiedName、Linq、false、new[]{file})调用类似CallGenericMethodThroughReflection的方法
/// 
///从哪个文件调用方法
///您可以获得类似assemblyQualifiedName的类型(Payroll.Domain.Attention.AttendanceApplicationMaster)。assemblyQualifiedName
/// 
/// 
/// 
///在给定方法具有重载的情况下传递参数类型列表
///调用方法的返回对象
公共静态对象调用GenericMethodThroughReflection(string assemblyQualifiedName,string methodName,bool isStaticMethod,object[]ParameterList,Type[]parameterType=null)
{
尝试
{
对象实例=null;
var bindingAttr=BindingFlags.Static | BindingFlags.Public;
如果(!isStaticMethod)
{
instance=Activator.CreateInstance();
bindingAttr=BindingFlags.Instance | BindingFlags.Public;
}
MethodInfo MI=null;
var type=type.GetType(assemblyQualifiedName);
if(参数类型==null)
MI=typeof(T).GetMethod(methodName,bindingAttr);
其他的
MI=typeof(T).GetMethod(methodName,bindingAttr,null,parameterType,null);//这在大多数情况下有效,但在某些情况下无效
if(type==null | | MI==null)//如果条件为true,则表示找不到给定的方法或AssemblyQualifiedName实体
返回null;
var genericMethod=MI.MakeGenericMethod(new[]{type});
返回genericMethod.Invoke(实例,paramaterList);
}
捕获(例外情况除外)
{
掷骰子;
}
}

我读到一个使用反射调用方法的解决方案。但我希望有另一种解决方案。invoke方法返回一个“Object”。在将该对象转换为正确类型之前,我无法查询该对象。(这可能是可行的)。我如何才能将对象强制转换为我拥有的类型?@Jan:你不能-但是你也不能使用该类型,因为你在编译时不知道该类型。。。这可能值得您编写一个泛型方法,它以强类型的方式完成您想要的一切,并使用反射调用它。或者,非泛型的
IQueryable
能满足您的需要吗?@Jon:谢谢,我会尝试编写自己的泛型方法。不幸的是,非泛型Iqueryable无法解决问题。@Jon:使用我自己的泛型方法调用另一个泛型方法解决了问题
typeof(Session).GetMethod("Linq").MakeGenericMethod(typeOne).Invoke(null, null);
typeof(DeclaringType).GetMethod("Linq").MakeGenericMethod(typeOne)
     .Invoke(null, new object[] {Session});
/// <summary>
    /// This method call your method through Reflection 
    /// so i wil call the method like CallGenericMethodThroughReflection<Session>(assemblyQualifiedName,Linq,false,new[] { file }) 
    /// </summary>
    /// <typeparam name="T">Call method from which file</typeparam>
    /// <param name="assemblyQualifiedName">Your can get assemblyQualifiedName like typeof(Payroll.Domain.Attendance.AttendanceApplicationMaster).AssemblyQualifiedName</param>
    /// <param name="methodName"></param>
    /// <param name="isStaticMethod"></param>
    /// <param name="paramaterList"></param>
    /// <param name="parameterType">pass parameter type list in case of the given method have overload  </param>
    /// <returns>return object of calling method</returns>
    public static object CallGenericMethodThroughReflection<T>(string assemblyQualifiedName, string methodName,bool isStaticMethod ,object[] paramaterList,Type[] parameterType = null)
    {
        try
        {
            object instance = null;
            var bindingAttr = BindingFlags.Static | BindingFlags.Public;
            if (!isStaticMethod)
            {
                instance = Activator.CreateInstance<T>();
                bindingAttr = BindingFlags.Instance | BindingFlags.Public;
            }
            MethodInfo MI = null;
            var type = Type.GetType(assemblyQualifiedName);
            if(parameterType == null)
                MI = typeof(T).GetMethod(methodName, bindingAttr);
            else
                MI = typeof(T).GetMethod(methodName, bindingAttr,null, parameterType, null);//this will work in most case some case not work
            if (type == null || MI == null) // if the condition is true it means given method or AssemblyQualifiedName entity not found
                return null;
            var genericMethod = MI.MakeGenericMethod(new[] { type });
            return genericMethod.Invoke(instance, paramaterList);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }