使用C#反射中的MAKEGENERICTYPE函数,来为泛型方法和泛型类指定(泛型的) ...

打印 上一主题 下一主题

主题 518|帖子 518|积分 1554

MakeGenericType 是一个在 C# 中用于创建开放范例的实例的方法。开放范例是一种未绑定范例参数的泛型范例。当你有一个泛型范例定义,并且想要用特定的范例实例化它时,你可以使用 MakeGenericType 方法。
  1. public Type MakeGenericType (params Type[] typeArguments);
复制代码
这个方法担当一个 Type[] 作为参数,此中包罗了用来更换泛型范例定义中的范例参数的范例。
比方,假设你有一个泛型类 Pair<T, U>,你想要创建一个 Pair<int, string> 的实例。你可以这样做:
  1. // 泛型类型定义
  2. public class Pair<T, U> {
  3.     public T First { get; set; }
  4.     public U Second { get; set; }
  5. }
  6. // 创建泛型类型的实例
  7. Type pairType = typeof(Pair<,>); // 获取开放类型
  8. Type[] typeArguments = { typeof(int), typeof(string) }; // 实例化类型参数
  9. Type pairInstanceType = pairType.MakeGenericType(typeArguments); // 创建实例类型
  10. // 创建实例
  11. object pairInstance = Activator.CreateInstance(pairInstanceType);
复制代码
在这个例子中,pairType 是一个开放范例,typeArguments 是用来更换 T 和 U 的详细范例。pairInstanceType 是一个已经绑定了详细范例参数的 Pair<int, string> 范例。最后,我们使用 Activator.CreateInstance 来创建这个范例的实例。

C#反射中的MakeGenericType函数可以用来指定泛型方法和泛型类的详细范例,方法如下面代码所示这里就不多讲了,详情看下面代码一切就清楚了:
  1. using System;
  2. using System.Reflection;
  3. namespace RFTest
  4. {
  5.     //类ReflectionTest中定义了一个泛型函数DisplayType和泛型类MyGenericClass
  6.     class ReflectionTest
  7.     {
  8.         //泛型类MyGenericClass有个静态函数DisplayNestedType
  9.         public class MyGenericClass<T>
  10.         {
  11.             public static void DisplayNestedType()
  12.             {
  13.                 Console.WriteLine(typeof(T).ToString());
  14.             }
  15.         }
  16.         public void DisplayType<T>()
  17.         {
  18.             Console.WriteLine(typeof(T).ToString());
  19.         }
  20.     }
  21.     class Program
  22.     {
  23.         static void Main(string[] args)
  24.         {
  25.             ReflectionTest rt = new ReflectionTest();
  26.             MethodInfo mi = rt.GetType().GetMethod("DisplayType");//先获取到DisplayType<T>的MethodInfo反射对象
  27.             mi.MakeGenericMethod(new Type[] { typeof(string) }).Invoke(rt, null);//然后使用MethodInfo反射对象调用ReflectionTest类的DisplayType<T>方法,这时要使用MethodInfo的MakeGenericMethod函数指定函数DisplayType<T>的泛型类型T
  28.             Type myGenericClassType = rt.GetType().GetNestedType("MyGenericClass`1");//这里获取MyGenericClass<T>的Type对象,注意GetNestedType方法的参数要用MyGenericClass`1这种格式才能获得MyGenericClass<T>的Type对象
  29.             myGenericClassType.MakeGenericType(new Type[] { typeof(float) }).GetMethod("DisplayNestedType", BindingFlags.Static | BindingFlags.Public).Invoke(null, null);
  30.             //然后用Type对象的MakeGenericType函数为泛型类MyGenericClass<T>指定泛型T的类型,比如上面我们就用MakeGenericType函数将MyGenericClass<T>指定为了MyGenericClass<float>,然后继续用反射调用MyGenericClass<T>的DisplayNestedType静态方法
  31.             Console.ReadLine();
  32.         }
  33.     }
  34. }
复制代码


C# 反射



反射是一种在运行时动态获取程序范例信息的技术,它可以用来查找和操纵程序中的范例、成员、属性和方法等。
(1)获取Type范例的几种方法:
(a)  实例调用GetType
(b)  typeof(范例)
(c)  Assembly.GetType(范例名称)
(d)  Type.GetType(范例全称)
(2)获取数组范例
typeof(范例).MakeArrayType()
如typeof(int).MakeArrayType()==typeof(int[]) //为true
(3)根据数组范例返回元素范例
typeof(int[]).GetElementType()==typeof(int)//为true
(4)范例具有Namespace,Name,FullName属性,FullName基本即是前两者组合在一起。
(5)数组,指针,ref,out 参数范例名称



MakeGenericType的使用:
MakeGenericType 方法用于创建一个泛型范例的实例,此中可以通过传递范例参数来指定详细的泛型参数范例。这在需要在运行时动态创建泛型范例的情况下非常有用。下面是一个示例代码演示怎样使用 MakeGenericType 方法:
假设有一个泛型类 MyGenericClass,你想要在运行时为其指定详细的范例参数并创建实例。首先,定义泛型类如下:

  1. using System;
  2. public class MyGenericClass<T>
  3. {
  4.     public void PrintType()
  5.     {
  6.         Console.WriteLine(typeof(T).Name);
  7.     }
  8. }
复制代码
接下来,可以使用 MakeGenericType 方法来动态创建泛型范例的实例:

  1. using System;
  2. class Program
  3. {
  4.     static void Main(string[] args)
  5.     {
  6.         // 获取泛型类型的定义
  7.         Type genericTypeDefinition = typeof(MyGenericClass<>);
  8.         // 指定泛型类型参数
  9.         Type[] typeArguments = { typeof(int) };
  10.         // 使用MakeGenericType创建泛型类型实例
  11.         Type specificType = genericTypeDefinition.MakeGenericType(typeArguments);
  12.         object instance = Activator.CreateInstance(specificType);
  13.         // 调用泛型类型的方法
  14.         var printMethod = specificType.GetMethod("PrintType");
  15.         printMethod.Invoke(instance, null);
  16.     }
  17. }
复制代码

在这个示例中,首先获取了泛型范例的定义 MyGenericClass<>,然后指定了详细的泛型范例参数,比方 int。接着使用 MakeGenericType 创建了指定参数的泛型范例实例,并通过 Activator.CreateInstance 创建了实例对象。最后,使用反射调用了泛型范例的方法。

  1. using System;
  2. using System.Reflection;
  3. class Program
  4. {
  5.     static void Main(string[] args)
  6.     {
  7.         // 通过反射查找类型
  8.         Type type = Type.GetType("Demo.Person");
  9.         // 通过反射创建对象
  10.         object person = Activator.CreateInstance(type);
  11.         // 通过反射调用方法
  12.         MethodInfo methodInfo = type.GetMethod("SayHello");
  13.         methodInfo.Invoke(person, null);
  14.         // 通过反射获取属性
  15.         PropertyInfo propertyInfo = type.GetProperty("Name");
  16.         Console.WriteLine("Name: {0}", propertyInfo.GetValue(person));
  17.         // 通过反射修改属性
  18.         propertyInfo.SetValue(person, "Tom", null);
  19.         Console.WriteLine("Name: {0}", propertyInfo.GetValue(person));
  20.         // 通过反射获取字段
  21.         FieldInfo fieldInfo = type.GetField("Age");
  22.         Console.WriteLine("Age: {0}", fieldInfo.GetValue(person));
  23.         // 通过反射修改字段
  24.         fieldInfo.SetValue(person, 20);
  25.         Console.WriteLine("Age: {0}", fieldInfo.GetValue(person));
  26.     }
  27. }
  28. class Person
  29. {
  30.     public string Name { get; set; }
  31.     public int Age;
  32.     public void SayHello()
  33.     {
  34.         Console.WriteLine("Hello, my name is {0}.", Name);
  35.     }
  36. }
复制代码
在这个示例中,我们通过反射查找了一个名为Demo.Person的范例,并创建了一个该范例的对象。然后,我们使用反射获取了该对象的SayHello方法,并通过Invoke方法调用了该方法。接着,我们使用反射获取了该对象的Name属性,并获取了该属性的值。然后,我们通过反射修改了该对象的Name属性的值,并再次获取了该属性的值。最后,我们使用反射获取了该对象的Age字段,并获取了该字段的值。然后,我们通过反射修改了该对象的Age字段的值,并再次获取了该字段的值。
·使用反射调用构造器,可以通过以下步调实现:
通过Type.GetType方法大概typeof关键字获取目标范例的Type对象。比方,获取Demo.Person范例的Type对象可以使用以下代码:Type type = Type.GetType("Demo.Person"); 大概 Type type = typeof(Demo.Person);




Activator.CreateInstance和constructor.Invoke都可以用于创建对象,但它们的实现方式有所差别。
Activator.CreateInstance是一个静态方法,它使用指定的范例名、程序集名、参数等信息来创建一个实例。它可以自动选择适当的构造函数进行创建,并且支持泛型范例的创建。使用Activator.CreateInstance可以避免手动获取构造函数的过程,让创建对象的过程更加简便。但是,由于其通过字符串来指定范例名和程序集名,因此需要在编译时指定完整的范例名和程序集名,不太方便动态获取范例。
constructor.Invoke则是使用反射获取到一个构造函数后,通过Invoke方法来调用构造函数,创建一个对象。与Activator.CreateInstance相比,使用constructor.Invoke需要手动获取构造函数,需要明确指定构造函数的参数,因此相对来说更加复杂。但是,它可以在运行时动态获取范例和构造函数,更加灵活。
总的来说,Activator.CreateInstance实用于已知范例名和程序集名的情况,可以让创建对象更加简便;而constructor.Invoke实用于需要动态获取范例和构造函数的情况,更加灵活。









免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南飓风

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表