none
反射: 如何知道一个对象类型的泛型参数类型? RRS feed

  • 问题

  • 对于任意未知的泛型对象, 如: object obj = new Dictionary<int, string>(); 或 object obj = new Tulpe<int, float, string>;

    1. 如何根据obj对象知道该对象包含几个泛型参数?

    2. 如何获取这些泛型参数的Type ?

    谢谢

    2011年2月9日 9:46

答案

  • 一下内容来自网络:

    泛型反射和普通反射的区别就是泛型参数的处理上。

    先看一个简单的例子。

    class Class1<T>
    {
      public void Test(T t)
      {
        Console.WriteLine(t);
      }
    }

    要利用反射动态创建该类型实例,并调用 Test 方法,我们可以使用如下方法。

    Type type = typeof(Class1<int>);
    object o = Activator.CreateInstance(type);
    type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, new object[] { 123 });

    但如果泛型参数是未定的,我们该如何处理呢?其实 Type 已经增加了类似的处理机制。

    static void InvokeTest(Type t, params object[] args)
    {
      Type type = typeof(Class1<>);
      type = type.MakeGenericType(t);
      object o = Activator.CreateInstance(type);
      type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, args);
    }

    另外一种情况就是泛型方法,我们继续。

    class Class1
    {
      public void Test<T>(T t)
      {
        Console.WriteLine(t);
      }
    }

    方法类似,只不过这回使用的是 MethodInfo.MakeGenericMethod()。

    static void InvokeTest(Type t, params object[] args)
    {
      Type type = typeof(Class1);
      object o = Activator.CreateInstance(type);
      MethodInfo method = type.GetMethod("Test", BindingFlags.Instance | BindingFlags.Public);

      method = method.MakeGenericMethod(t);
      method.Invoke(o, args);
    }

     

     


    family as water
    2011年2月9日 11:41
  • 您好,请参考:

               Object dic = new Dictionary<int, string>();
                foreach (Type type in dic.GetType().GetGenericArguments())
                {
                    Console.WriteLine("\r\nGenericArgumentType: {0}", type);
                }

    2011年2月9日 12:08
    版主
  • 为答谢各位高手的厚爱,小弟现将最近我经常提问并得到解答的有关反射和反射范型的问题总结如下。希望对其它朋友也有所帮助。

    1.通过字符串反射带泛型参数的类。 使用字符反撇---键盘1左边的那个键。
     Type listType = Type.GetType(“System.Generic.List'1”); //List<T>
     Type dicType = Type.GetType(“System.Generic.Dictionary'2”); //Dictionary<K,V>
    
    2.识别一个class对象在定义时是否被标记有某个Attribute。
     //原始定义
     [MyAttribute]
     class MyClass{}
     //演示代码代码
     object myObj = new MyClass();
     Attribute atb = System.Attribute.GetCustomAttribute //的到该类定义上制定的属性
             ( obmyObj.GetType, typeof(MyAttribute),false );
             //或者直接获得类定义时的全部属性
             System.Attribute.GetCustomAttributes( obmyObj.GetType);
    
    3。判断一个自定义类的实例是否在别的类中作为proptise时被标记了Attribute
      //原始定义。
      class MyClass{} //自己本身的类定义没有被标记Attribute
      class OtherClass
      {
       [MyAttribute]
       MyClass MyObj; //作为其他类的proptise时被标记了Attribute
      }
     
      演示代码
      OtherClass otherObj = new OtherClass();
      FieldInfo[] fields = otherObj.GetFields(BindingFlags.Public |
                BindingFlags.NonPublic | BindingFlags.Instance);
      foreach (FieldInfo field in fields)
      {
        Attribute atb = System.Attribute.GetCustomAttribute(
              field, //这里是关键。一定是field,而不是field.FieldType
              typeof(MyAttribute), false);
    
        Assert.IsNotNull(atb, "获取MyAttribute失败");
      }
    
    4. 遍历一个未知类型的所有泛型参数定义
      Object dic = new Dictionary<int, string>();
      foreach (Type type in dic.GetType().GetGenericArguments()) //这里是关键 
      {
        Console.WriteLine("\r\nGenericArgumentType: {0}", type);
      }
    
    5。反射创建未知泛型的实例
      //以List<int>为例
      Type classType = typeof(List<>); //List<>也可以也可以扩展为别的地方传来的参数。
      Type genericType = classType.MakeGenericType(typeof(int)); //这里的typeof(int)也可以扩展为别的地方传来的参数。
      object o = Activator.CreateInstance(type);创建实例。 
      //当然了。这个例子是一个泛型参数的例子。 对于不确定泛型个数的,可以首先通过上一个例子(4)
      //先从obj.GetType().GetGenericArguments()获取全部泛型信息后再进行初始化使用。
    
    6。反射得到Array类型中元素的数据类型。
      string[] obj = new string[]; //模拟一个未知的数组
      Type objType = obj.GetType(); //首先得到数组的Type
      Type elementType = objType.GetElementType(); 然后得到数组内部元素的Type
    
    
    
    
    

     

    2011年2月10日 14:22

全部回复

  • 一下内容来自网络:

    泛型反射和普通反射的区别就是泛型参数的处理上。

    先看一个简单的例子。

    class Class1<T>
    {
      public void Test(T t)
      {
        Console.WriteLine(t);
      }
    }

    要利用反射动态创建该类型实例,并调用 Test 方法,我们可以使用如下方法。

    Type type = typeof(Class1<int>);
    object o = Activator.CreateInstance(type);
    type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, new object[] { 123 });

    但如果泛型参数是未定的,我们该如何处理呢?其实 Type 已经增加了类似的处理机制。

    static void InvokeTest(Type t, params object[] args)
    {
      Type type = typeof(Class1<>);
      type = type.MakeGenericType(t);
      object o = Activator.CreateInstance(type);
      type.InvokeMember("Test", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, args);
    }

    另外一种情况就是泛型方法,我们继续。

    class Class1
    {
      public void Test<T>(T t)
      {
        Console.WriteLine(t);
      }
    }

    方法类似,只不过这回使用的是 MethodInfo.MakeGenericMethod()。

    static void InvokeTest(Type t, params object[] args)
    {
      Type type = typeof(Class1);
      object o = Activator.CreateInstance(type);
      MethodInfo method = type.GetMethod("Test", BindingFlags.Instance | BindingFlags.Public);

      method = method.MakeGenericMethod(t);
      method.Invoke(o, args);
    }

     

     


    family as water
    2011年2月9日 11:41
  • 您好,请参考:

               Object dic = new Dictionary<int, string>();
                foreach (Type type in dic.GetType().GetGenericArguments())
                {
                    Console.WriteLine("\r\nGenericArgumentType: {0}", type);
                }

    2011年2月9日 12:08
    版主
  • dear
    参考下列文章,看看有無帮助。

    [.NET] 使用 Reflection 呼叫泛型方法
    http://www.dotblogs.com.tw/regionbbs/archive/2011/02/09/invoke.generic.methods.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/
    2011年2月10日 0:55
  • dear
    参考下列文章,看看有無帮助。

    [.NET] 使用 Reflection 呼叫泛型方法
    http://www.dotblogs.com.tw/regionbbs/archive/2011/02/09/invoke.generic.methods.aspx


    秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/


    非常感谢。

    不过该文章的作者好像不知道如何通过字符串反射带范型 type:Type exampleClass = Type.GetType(“ExampleClass<>”);

    这句话的正确写法应该是 Type exampleClass = Type.GetType(“ExampleClass`1”);

    2011年2月10日 13:46
  • 为答谢各位高手的厚爱,小弟现将最近我经常提问并得到解答的有关反射和反射范型的问题总结如下。希望对其它朋友也有所帮助。

    1.通过字符串反射带泛型参数的类。 使用字符反撇---键盘1左边的那个键。
     Type listType = Type.GetType(“System.Generic.List'1”); //List<T>
     Type dicType = Type.GetType(“System.Generic.Dictionary'2”); //Dictionary<K,V>
    
    2.识别一个class对象在定义时是否被标记有某个Attribute。
     //原始定义
     [MyAttribute]
     class MyClass{}
     //演示代码代码
     object myObj = new MyClass();
     Attribute atb = System.Attribute.GetCustomAttribute //的到该类定义上制定的属性
             ( obmyObj.GetType, typeof(MyAttribute),false );
             //或者直接获得类定义时的全部属性
             System.Attribute.GetCustomAttributes( obmyObj.GetType);
    
    3。判断一个自定义类的实例是否在别的类中作为proptise时被标记了Attribute
      //原始定义。
      class MyClass{} //自己本身的类定义没有被标记Attribute
      class OtherClass
      {
       [MyAttribute]
       MyClass MyObj; //作为其他类的proptise时被标记了Attribute
      }
     
      演示代码
      OtherClass otherObj = new OtherClass();
      FieldInfo[] fields = otherObj.GetFields(BindingFlags.Public |
                BindingFlags.NonPublic | BindingFlags.Instance);
      foreach (FieldInfo field in fields)
      {
        Attribute atb = System.Attribute.GetCustomAttribute(
              field, //这里是关键。一定是field,而不是field.FieldType
              typeof(MyAttribute), false);
    
        Assert.IsNotNull(atb, "获取MyAttribute失败");
      }
    
    4. 遍历一个未知类型的所有泛型参数定义
      Object dic = new Dictionary<int, string>();
      foreach (Type type in dic.GetType().GetGenericArguments()) //这里是关键 
      {
        Console.WriteLine("\r\nGenericArgumentType: {0}", type);
      }
    
    5。反射创建未知泛型的实例
      //以List<int>为例
      Type classType = typeof(List<>); //List<>也可以也可以扩展为别的地方传来的参数。
      Type genericType = classType.MakeGenericType(typeof(int)); //这里的typeof(int)也可以扩展为别的地方传来的参数。
      object o = Activator.CreateInstance(type);创建实例。 
      //当然了。这个例子是一个泛型参数的例子。 对于不确定泛型个数的,可以首先通过上一个例子(4)
      //先从obj.GetType().GetGenericArguments()获取全部泛型信息后再进行初始化使用。
    
    6。反射得到Array类型中元素的数据类型。
      string[] obj = new string[]; //模拟一个未知的数组
      Type objType = obj.GetType(); //首先得到数组的Type
      Type elementType = objType.GetElementType(); 然后得到数组内部元素的Type
    
    
    
    
    

     

    2011年2月10日 14:22
  • 支持和倡议您的做法,利己利人!赞~ 顶~
    2011年2月11日 11:44
    版主
  • Hi Charles,

    替论坛的朋友们感谢你的总结,顶上去。

    Nice day,
    Leo Liu
    Leo Liu [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2011年2月16日 2:54
    版主