【问题标题】:C# use System.Type as Generic parameterC# 使用 System.Type 作为通用参数
【发布时间】:2011-06-07 18:25:11
【问题描述】:

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

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

Session.Linq<MyType>()

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

我拥有的是:

System.Type typeOne;

但我无法执行以下操作:

Session.Linq<typeOne>()

如何将类型用作通用参数?

【问题讨论】:

    标签: c# generics .net-4.0 types


    【解决方案1】:

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

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

    【讨论】:

    • 我读到了一个使用反射来调用方法的解决方案。但我希望有另一种解决方案。
    • invoke 方法返回一个“对象”。在将其转换为正确的类型之前,我无法查询此对象。 (这可能是 IQueryable) 。如何将对象转换为我拥有的类型?
    • @Jan:你不能——但是你也不能使用那个类型,因为你在编译时不知道类型......这可能是值得你编写一个通用方法,它以强类型的方式完成你想要的一切,并用反射调用 that。或者,非通用 IQueryable 是否满足您的需求?
    • @Jon:谢谢,我会尝试编写自己的通用方法。不幸的是,非泛型 Iqueryable 无法解决问题。
    • @Jon: 使用我自己的泛型方法调用另一个泛型方法解决了问题
    【解决方案2】:

    为此,您需要使用反射:

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

    (假设Linq&lt;T&gt;()Session类型的静态方法)

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

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

    【讨论】:

      【解决方案3】:

      我有一种通用方法,通过反射调用通用方法

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多