在 C# 中,Type
类是反射(Reflection)机制的核心部分。反射使你能够在运行时获取类型的信息,并对这些类型进行操作。本文将详细介绍 Type
类及其常用方法和用法。通过这篇教程,你将学习如何获取类型的元数据、调用方法、创建实例等操作。
什么是 Type 类?
Type
类属于 System
命名空间,是 C# 反射机制的核心。它提供了用于获取类型信息的属性和方法,比如类的名称、命名空间、方法、属性、字段等。通过 Type
类,你可以动态地操作类型,这在需要处理动态类型或者插件系统时特别有用。
获取 Type 对象
在使用 Type
类之前,首先需要获取 Type
对象。获取 Type
对象的方式有多种,为了方便讲解,我们先创建一个MyClass类。
public class MyClass
{
public int MyProperty { get; set; }
public void MyMethod()
{
Console.WriteLine("MyMethod called");
}
public void MyMethodWithParameters(int param1, string param2)
{
Console.WriteLine($"MyMethodWithParameters called with param1: {param1}, param2: {param2}");
}
public int PublicField;//公共字段
private string PrivateField;//私有字段
}
使用 typeof 关键字
这是获取 Type
对象的最常见方式之一,通过关键字typeof和类名获取类型
Type type = typeof(MyClass);
使用 GetType 方法
如果你已经有一个对象实例,可以通过该对象的 GetType
方法获取 Type
对象:
MyClass obj = new MyClass();
Type type = obj.GetType();
使用 Type.GetType 方法
你还可以通过类型的完全限定名(包含命名空间和程序集名称)来获取 Type
对象:
Type type = Type.GetType("Namespace.MyClass, AssemblyName");
获取类型信息
一旦获取了 Type
对象,就可以使用它来获取类型的各种信息。
获取类型的名称
你可以使用 Name
属性获取类型的名称:
string typeName = type.Name;
Console.WriteLine("类型名称:" + typeName);
获取类型的命名空间
使用 Namespace
属性可以获取类型的命名空间:
string namespaceName = type.Namespace;
Console.WriteLine("命名空间:" + namespaceName);
获取类型的程序集
通过 Assembly
属性可以获取类型所在的程序集:
Assembly assembly = type.Assembly;
Console.WriteLine("程序集:" + assembly.FullName);
获取类型的成员
通过 Type
类,你可以获取类型的各种成员信息,比如属性、方法、字段等。
获取类型的所有属性
使用 GetProperties
方法可以获取类型的所有属性:
PropertyInfo[] properties = type.GetProperties();
Console.WriteLine("属性列表:");
foreach (var property in properties)
{
Console.WriteLine(property.Name);
}
获取类型的所有方法
使用 GetMethods
方法可以获取类型的所有方法:
MethodInfo[] methods = type.GetMethods();
Console.WriteLine("方法列表:");
foreach (var method in methods)
{
Console.WriteLine(method.Name);
}
获取类型的所有字段
使用 GetFields
方法可以获取类型的所有字段:
FieldInfo[] fields = type.GetFields();
Console.WriteLine("字段列表:");
foreach (var field in fields) //只能获取公有字段
{
Console.WriteLine(field.Name);
}
//获取所有字段,包括私有字段
FieldInfo[] fields2 = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Console.WriteLine("字段列表:");
foreach (var field in fields2)
{
Console.WriteLine(field.Name);
}
反射调用方法
反射不仅可以获取类型的信息,还可以动态调用类型的方法。以下是一些常见的反射调用方法的示例:
调用无参数方法
首先,获取方法的 MethodInfo
对象,然后使用 Invoke
方法调用它:
MethodInfo method = type.GetMethod("MyMethod");
if (method != null)
{
method.Invoke(obj, null);
}
调用带参数的方法
如果方法带有参数,需要在 Invoke
方法中传入参数数组:
MethodInfo method = type.GetMethod("MyMethodWithParameters");
if (method != null)
{
object[] parameters = new object[] {100, "sunny" };
method.Invoke(obj, parameters);
}
创建实例
你还可以使用反射创建类型的实例。这对于某些需要在运行时决定实例化哪个类的场景非常有用。
创建无参数构造函数的实例
使用 Activator.CreateInstance
方法可以创建类型的实例:
object instance = Activator.CreateInstance(type);
创建带参数构造函数的实例
如果构造函数需要参数,可以在 CreateInstance
方法中传入参数数组:
object[] parameters = new object[] { param1, param2 };
object instance = Activator.CreateInstance(type, parameters);
综合示例
下面是一个综合示例,展示如何使用 Type
类获取类型信息并进行反射调用:
//通过类获取类型
using System.Reflection;
Type type = typeof(MyClass);
Console.WriteLine(type);
//通过实例取类型
var instance = new MyClass();
Type type1 = instance.GetType();
Console.WriteLine(type1);
Console.WriteLine("程序集:" + type.Assembly.FullName);
//获取公有字段
FieldInfo[] fields = type.GetFields();
//获取私有字段
FieldInfo[] fields2 = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
Console.WriteLine("字段列表:");
foreach (var field in fields2)
{
Console.WriteLine(field.Name);
}
// 调用无参数方法
MethodInfo method1 = type.GetMethod("MyMethod");
method1.Invoke(instance, null);
// 调用参数方法
MethodInfo method = type.GetMethod("MyMethodWithParameters");
if (method != null)
{
object[] parameters = new object[] {100, "sunny" };
method.Invoke(instance, parameters);
}
//创建实例
object instance2 = Activator.CreateInstance(type);
Console.WriteLine(instance2);
public class MyClass
{
public int MyProperty { get; set; }
public void MyMethod()
{
Console.WriteLine("MyMethod called");
}
public void MyMethodWithParameters(int param1, string param2)
{
Console.WriteLine($"MyMethodWithParameters called with param1: {param1}, param2: {param2}");
}
public int PublicField;//公共字段
private string PrivateField;//私有字段
}