代码之家  ›  专栏  ›  技术社区  ›  dkackman Srinivas Kokkula

有没有办法确定泛型类型是否是从特定泛型类型定义生成的?

  •  4
  • dkackman Srinivas Kokkula  · 技术社区  · 14 年前

    我有一个通用方法:

    Func<IEnumerable<T>, bool> CreateFunction<T>()
    

    哪里 T 可以是任意数量的不同类型。这个方法使用反射和if来做很多事情 T型 IDictionary ,不管字典里的 TKey TValue

    var f = CreateFunction<string>();
    var f0 = CreateFunction<SomePocoType>();
    var f1 = CreateFunction<IDictionary<string,object>>();
    var f2 = CreateFunction<Dictionary<string,object>>();
    var f3 = CreateFunction<SomeDerivedDictionaryType<string,object>>();
    

    等。

    根据@Andy的回答澄清

    词典 T型 Dictionary 或者从该接口派生的其他类型。

    if(typeof(T) == typeof(IDictionary<,>)
    

    不起作用是因为 是泛型类型而不是泛型类型定义。

    而且不知道 t值 (编译时不知道)在运行时之前,我无法与任何具体类型进行比较。

    我想到的唯一一件事就是查看类型的名称,或者用反射检查它的方法,寻找使我相信它是字典的方法(即查找 ContainsKey get_Item ).

    4 回复  |  直到 14 年前
        1
  •  2
  •   Jamie Altizer    14 年前

    你可以这样做

    class Program
    {
        static void Main(string[] args)
        {
            Example<IDictionary<int, string>>.IsDictionary();
    
            Example<SortedDictionary<int, string>>.IsDictionary();
    
            Example<Dictionary<int, string>>.IsDictionary();
    
            Console.ReadKey();
        }
    }
    
    public class Example<T>
    {
        public static void IsDictionary()
        {
            if (typeof(T).GetInterface(typeof(IDictionary<,>).Name) != null || typeof(T).Name.Contains("IDictionary"))
            {
                Console.WriteLine("Is IDictionary");
            }
            else
            {
                Console.WriteLine("Not IDictionary");
            }
        }
    }
    
        2
  •  7
  •   Nathan Baulch    14 年前

    您可以使用 IsGenericType GetGenericTypeDefinition 成员如下:

    var type = typeof (T);
    if (typeof (IDictionary).IsAssignableFrom(type))
    {
        //non-generic dictionary
    }
    else if (type.IsGenericType &&
             type.GetGenericTypeDefinition() == typeof (IDictionary<,>))
    {
        //generic dictionary interface
    }
    else if (type.GetInterfaces().Any(
                i => i.IsGenericType &&
                     i.GetGenericTypeDefinition() == typeof (IDictionary<,>)))
    {
        //implements generic dictionary
    }
    
        3
  •  4
  •   Gabe Timothy Khouri    14 年前

    Type iDict = null;
    if (typeof(T).GetGenericTypeDefinition() == typeof(IDictionary<,>))
        iDict = typeof(T);
    else
        iDict = typeof(T).GetInterface(typeof(IDictionary<,>).Name);
    if (iDict != null)
    {
        var genericParams = iDict.GetGenericArguments();
        Type tKey = genericParams[0], tValue = genericParams[1];
    }
    

    请注意,如果 T 不止一个 IDictionary<,> 接口,但这对于您的目的可能是好的。

    为了完整性,这里有一个实现 使用多个 i词典<,> 使用第一个接口:

    Type iDict = t.GetType().GetInterfaces()
                  .Where(t => t.IsGenericType
                   && t.GetGenericTypeDefinition() == typeof(IDictionary<,>))
                  .FirstOrDefault();
    if (iDict != null)
    {
        var genericParams = iDict.GetGenericArguments();
        Type tKey = genericParams[0], tValue = genericParams[1];
    }
    

    注意,在第二个例程中 t 是一个对象,而 T型 是第一个例程中的类型。

        4
  •  0
  •   Andy    14 年前

    我想如果你打电话 Type.GetGenericTypeDefinition() 它应该返回用于构造具体类型的“基”泛型类型。

    请注意,将此与 IDictionary<,> Dictionary<,> 我想你也会用这个。您可以检查类型是否实现 i词典<,> Type.IsAssignableFrom()