What-反射是什么?
反射,Reflection,就是通过一个类对象,可以获取他所在类的其他全部成员和属性,包括私有的。
Why-为什么要使用反射?
1.获取该成员的其他属性信息来使用
可以使用一些奇思淫巧来加快开发速度,减少代码的入侵性,提高代码的可维护性。
譬如,表单 / 表格是页面中常见的元素。在实战中,我们想将字段名或列名定义在实体类model中,并为这些成员添加一系列注解,之后,我想要将这个model对象作为参数传入某个方法,在这个方法中,我会拿出类中所有成员变量上定义的注解。作为我们的字段名或列名。这样是不是就方便多了。如果想实现这种代码思路,就需要使用反射。
2.配合泛型,写出通用的一个工具类,一般用于框架性的代码
接着上个例子,我现在有两个表格,部门表和员工表,所以有两个类,部门model,员工model.这个时候,可以使用泛型类型传参,然后通过反射获取传过来的类型的自定义注解信息
3.例如反射获取一个类的私有方法或者属性
需要用到一个类里面的方法,但是这个方法是不对外暴露的,怎么办?我们不怕,因为我们有反射.
How-使用反射?
快速入门:
using System;
using System.Reflection;
using System.Text;
namespace ConsoleApp
{
public enum GenderEnum { Boy = 0, Girl = 1, Dog = 2 }
class Program
{
static void Main(string[] args)
{
Console.OutputEncoding = Encoding.Unicode; // 输入
Console.InputEncoding = Encoding.Unicode; // 输出
/* ============================================== */
WorkerModel worker = new WorkerModel();
// 得到对象的类型
Type type = worker.GetType();
// 得到字段字段信息,只能得到public类型的值
FieldInfo[] fieldInfos = type.GetFields();
foreach (var f in fieldInfos) {
string fieldName = f.Name;
string fieldType = f.FieldType.ToString();
string fieldValue = f.GetValue(worker).ToString();
Console.WriteLine("字段名 = {0} | 字段类型 = {1} | 字段值 = {2}", fieldName, fieldType, fieldValue);
}
/* ============================================== */
Console.ReadLine();
}
}
public class WorkerModel
{
/// <summary>
/// 字段
/// </summary>
public string _name = "Hathway";
private int _id = 32;
protected bool _isAdmin = true;
public GenderEnum _gender = GenderEnum.Girl;
/// <summary>
/// 属性
/// </summary>
public string Name { get; set; }
public GenderEnum Gender { get; set; }
private int Id { get; set; }
protected bool IsAdmin { get; set; }
/// <summary>
/// 方法
/// </summary>
public void Android() { }
protected void IOS() { }
private void WindowPhone() { }
/// <summary>
/// 构造方法
/// </summary>
public WorkerModel(){ }
public WorkerModel(string name, int id, GenderEnum gender, bool isAdmin) { }
}
}
public怎么够? 获取受保护的、私有的成员信息: BindingFlags
替换以下两处代码,然后试试
// 替换A:
// WorkerModel worker = new WorkerModel();
WorkerModel worker = new WorkerModel() {
Name = "Jay",
Gender = GenderEnum.Boy,
};
// 替换B:
// FieldInfo[] fieldInfos = type.GetFields();
/**
* 得到字段的值,包括private、protected、public的值
* 以下三个BindingFlags枚举,按顺序称之为1、2、3
* 1 - NonPublic: 指定非Public修饰的成员
* 2 - Public: 指定Public修饰的成员
* 3 - Instance: 指定实例成员将包括在搜索中。
* 使用特别注意!!!
* 测试发现: 12组合获取为空, 而13、23组合方式获取到了
* 原因是官方规定:必须与Public 或 NonPublic 一起指定 Instance 或 Static, 否则将不返回成员。
*/
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
除了 GetFields 得到字段信息,还有其他的如:GetProperties(属性)、GetMethods(方法)、GetMembers(成员)、GetConstructors(构造方法)。这些函数都支持使用 BindingFlags
/// <summary>
/// 属性信息
/// </summary>
/// <param name="obj"></param>
public static void GetPropertyInfo(Object obj)
{
Type type = obj.GetType();
PropertyInfo[] propertyInfo = type.GetProperties();
foreach (var p in propertyInfo) {
string propertyName = p.Name;
string propertyValue = p.GetValue(obj, null).ToString();
Console.WriteLine("属性名 = {0} | 属性值 = {1}", propertyName, propertyValue);
}
}
/// <summary>
/// 方法信息
/// </summary>
/// <param name="obj"></param>
public static void GetMethodInfo(Object obj)
{
Type type = obj.GetType();
//获取所有public修饰的方法
MethodInfo[] methodInfo = type.GetMethods();
foreach (var m in methodInfo) {
string methodName = m.Name;
Console.WriteLine("方法名 = {0}", methodName);
}
}
/// <summary>
/// 成员信息
/// </summary>
/// <param name="obj"></param>
public static void GetMemberInfo(Object obj)
{
Type type = obj.GetType();
MemberInfo[] memberInfo = type.GetMembers();
foreach (var m in memberInfo) {
string memberName = m.Name;
Console.WriteLine("成员名 = {0}", memberName);
}
}
/// <summary>
/// 构造方法信息
/// </summary>
/// <param name="obj"></param>
private static void GetConstructorInfo(Object obj)
{
Type type = obj.GetType();
//获取所有public修饰的构造方法
ConstructorInfo[] constructorInfo = type.GetConstructors();
foreach (var c in constructorInfo) {
string constructorName = c.Name;
ParameterInfo[] constructorParams = c.GetParameters();
Console.WriteLine("constructorName------>" + constructorName);
foreach (var p in constructorParams) {
Console.WriteLine("Params------ p.Name-->" + p.Name);
Console.WriteLine("Params------ p.Type--->" + p.ParameterType);
}
}
}