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);
        }
    }
}

results matching ""

    No results matching ""