拆解,查询和重新组装通用类型

时间:2013-03-21 20:26:40

标签: c# generics

我有一个方法

T Get<T>(string key)
{..
}

如果来电者用T = IEnumerable<V>给我打电话,我需要这样做:

return GetEnum<V>(key)

因此我需要

  • 测试T是IEnumerable<X>
  • 获取X并将其推入GetEnum 方法

我怀疑我不能做第二次

显然我可以编写一个不同的方法,但这不是我与现有代码库的契约。

1 个答案:

答案 0 :(得分:2)

你可以稍微反思一下,但不会特别快:

static class TheClass
{
   public static T Get<T>(string key)
   {
      // Adjust these as required:
      const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;

      if (typeof(T).IsGenericType && typeof(IEnumerable<>) == typeof(T).GetGenericTypeDefinition())
      {
         Type v = typeof(T).GetGenericArguments()[0];
         var baseMethod = typeof(TheClass).GetMethod("GetEnum", flags);
         var realMethod = baseMethod.MakeGenericMethod(v);
         return (T)(object)realMethod.Invoke(null, new[] { key });
      }

      // TODO: Handle other types...
   }

   private static IEnumerable<T> GetEnum<T>(string key)
   {
      // TODO: Return an enumerable...
   }
}

修改
如果要检查所需的返回类型是否实现 IEnumerable<>,您可以使用:

Type enumerable = typeof(T).GetInterface("System.Collections.Generic.IEnumerable`1");
if (enumerable != null)
{
   Type v = enumerable.GetGenericArguments()[0];
   var baseMethod = typeof(TheClass).GetMethod("GetEnum", flags);
   var realMethod = baseMethod.MakeGenericMethod(v);
   return (T)(object)realMethod.Invoke(null, new[] { key });
}

但是,您的GetEnum<V>方法必须返回一个可以转换为T的值,否则您将获得无效的强制转换异常。

例如,如果您的GetEnum<V>方法返回new List<T>(...),则Get<T>方法仅在TList<T>或由List<T>。如果您致电Get<HashSet<int>>,则会失败。