引言
最近有在 .NET 平台搭建 API Automation Framework, 就有遇到怎么将字符串类名转换成类,并访问其常量属性,很久没有弄 .NET 的东西,很是生疏。所以特意研究了一下,利用 Reflection 反射就可以解决这个问题。
内容提要:
- 反射 Reflection 的几个主要方法
- 完整代码举例
反射 Reflection 的几个主要方法
介绍一下几个要点:
- 引用 Reflection
using System.Reflection;
- 字符串转换成类
注意要加上 namespace
Type type = Type.GetType(namespaceStr + "." + className);
- 访问字段,返回字段数组
默认是访问所有 public 的字段,包括父类继承的字段
FieldInfo[] default_fields = type.GetFields();
当然也可以加上条件过滤一下,下面是访问所有 private, public 的字段。
FieldInfo[] all_fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
有在 BindingFlags 选项可以参考源代码中的注释:
- 访问单个字段值
注意这种方式只能访问类字段,访问实例变量是会抛异常的
。
type.GetField("Const_Field_Name").GetValue(type)
注意上述方法不能访问父类的常量字段,可以通过 BaseType 得到父类 Type
type.BaseType.GetField("Parent_Const_field_name").GetValue(type)
- 方法调用
MethodInfo method = type.GetMethod("Method_Name");
method.Invoke(instance_object, object[] parameters);
- 实例化类对象
object instance_object = Activator.CreateInstance(type);
完整代码举例
将上面介绍的点串起来应用一下, 定义了一对父子类,分别有不同的字段和方法,通过反射 Reflection 来访问其不同字段和方法,通过程序运行结果,可以更好的理解代码。
using System.Reflection;
namespace ConsoleApp1
{
public class ParentClass
{
public const string P_CONST_STR = "Parent Const str";
private string p_private_str = "Private str";
public string p_public_Str = "Public str";
public void P_Method_call(string p1,string p2)
{
Console.WriteLine("P Method_call" + " with parameter " + p1 + " and " + p2);
}
}
public class childClass : ParentClass
{
public const string C_CONST_STR = "Child Const str";
private string c_private_str = "Private str";
public string c_public_Str = "Public str";
public void C_Method_call()
{
Console.WriteLine("C Method_call");
}
}
public class Test
{
static void Main(string[] args)
{
string namespaceStr = "ConsoleApp1";
string className = "childClass";
Type child_type = Type.GetType(namespaceStr + "." + className);
FieldInfo[] all_fields = child_type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
FieldInfo[] default_fields = child_type.GetFields();
Console.WriteLine("====All Fields:====");
foreach (FieldInfo field in all_fields)
{
Console.WriteLine(field.Name);
}
Console.WriteLine("====Default Fields Without Filters:====");
foreach (FieldInfo field in default_fields)
{
Console.WriteLine(field.Name);
}
Console.WriteLine("====Acess Const Field Value:====");
Console.WriteLine("Acess const field value: " + child_type.GetField("C_CONST_STR").GetValue(child_type));
Console.WriteLine("Acess const field value: " + child_type.BaseType.GetField("P_CONST_STR").GetValue(child_type));
Console.WriteLine("====Call Methods:====");
MethodInfo c_method = child_type.GetMethod("C_Method_call");
MethodInfo p_method = child_type.GetMethod("P_Method_call");
object instance_child = Activator.CreateInstance(child_type);
c_method.Invoke(instance_child, null);
object[] parameterObject = new object[] {"p1_value", "p2_value"};
p_method.Invoke(instance_child, parameterObject);
}
}
}
输出:
====All Fields:====
c_private_str
c_public_Str
C_CONST_STR
p_public_Str
====Default Fields Without Filters:====
c_public_Str
C_CONST_STR
p_public_Str
====Acess Const Field Value:====
Acess const field value: Child Const str
Acess const field value: Parent Const str
====Call Methods:====
C Method_call
P Method_call with parameter p1_value and p2_value