【问题标题】:How to get the type contained in a collection through reflection如何通过反射获取集合中包含的类型
【发布时间】:2010-12-26 09:36:48
【问题描述】:

在我的代码的某些部分,我传递了一个T 类型的对象集合。我不知道我会通过哪个具体的集合,除了它会影响IEnumerable

在运行时,我需要找出 T 是哪种类型(例如System.DoubleSystem.String 等...)。

有什么办法可以查到吗?

更新:我可能应该多澄清一下我工作的环境(Linq 提供者)。

我的函数具有如下签名,其中我将集合的类型作为参数获取:

string GetSymbolForType(Type collectionType)
{

}

collectionType 有什么方法可以获取包含的对象类型吗?

【问题讨论】:

  • 从集合类型中只能获取泛型集合中包含的对象的类型。如果您使用经典集合,除了迭代对象并专门询问它们的类型之外,您将没有很好的机会。

标签: c# reflection collections


【解决方案1】:

来自Matt Warren's Blog

internal static class TypeSystem {
    internal static Type GetElementType(Type seqType) {
        Type ienum = FindIEnumerable(seqType);
        if (ienum == null) return seqType;
        return ienum.GetGenericArguments()[0];
    }
    private static Type FindIEnumerable(Type seqType) {
        if (seqType == null || seqType == typeof(string))
            return null;
        if (seqType.IsArray)
            return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
        if (seqType.IsGenericType) {
            foreach (Type arg in seqType.GetGenericArguments()) {
                Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
                if (ienum.IsAssignableFrom(seqType)) {
                    return ienum;
                }
            }
        }
        Type[] ifaces = seqType.GetInterfaces();
        if (ifaces != null && ifaces.Length > 0) {
            foreach (Type iface in ifaces) {
                Type ienum = FindIEnumerable(iface);
                if (ienum != null) return ienum;
            }
        }
        if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
            return FindIEnumerable(seqType.BaseType);
        }
        return null;
    }
}

【讨论】:

    【解决方案2】:
    myCollection.GetType().GetGenericArguments() 
    

    将返回一个 args 类型的数组。

    【讨论】:

      【解决方案3】:
      Type t = null
      foreach(object o in list)
      {
      o.GetType();
      }
      

      将为您提供对象的类型。

      那么你可能应该测试你想要的类型:

      if(t == typeof(myClass))
      {
      dosomething();
      }
      else if (t == typeof(myOtherClass))
      {
      dosomethingelse();
      }
      

      【讨论】:

        【解决方案4】:

        我经常使用动态,这是不时出现的问题。

        Matt Davis 成功了,但你需要索引 :)

        public static void PopulateChildCollection<T>(T currentObject, string singlePropertyName)
        {
          dynamic currentObjectCollection = ReflectionTools.GetPropertyValue(currentObject, singlePropertyName);
          Type collectionType = currentObjectCollection.GetType().GetGenericArguments()[0];
        

        类型将是您所期望的,它是集合中包含的对象的类型,而不是围绕它的任何泛型类型。

        【讨论】:

          【解决方案5】:

          你不能只使用 t.GetType() 来做到这一点。

          【讨论】:

            【解决方案6】:

            为什么不直接实现 IEnumerable&lt;T&gt; 呢?例如:

            public void MyFunc&lt;T&gt;(IEnumerable&lt;T&gt; objects)

            除此之外,您最好使用is.GetType 检查每个单独对象的类型,而不是尝试从容器本身中计算出来。

            如果这不是一个选项,并且您确实需要知道基本容器的类型,您基本上必须使用is 检查它实现的接口(例如:IList&lt;int&gt; 等)。奇怪的是你的数组的类型将是一个泛型,这意味着试图从它的名称返回到它的数据类型将会非常混乱。

            【讨论】:

              【解决方案7】:

              好吧,我来晚了,但不应该这样工作:

                public static bool ThatCollectionIsOfType<T>(IEnumerable<T> collection, Type got)
                {
                       if (**typeof(T)** == got) //this line should be good to go...
                       {
                          return true;
                       }
              
                 }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-04-02
                • 1970-01-01
                • 2010-10-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多