C#数据结构--反射

反射是程序可以访问、检测、修改它本身状态或行为一种能力。
程序集包括模块,模块包括类型,类型又包括成员。反射可以提供封装程序集、模块和类型的对象。
反射可以动态的创建类型的实例,把类型绑定在现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。

(1)反射dll得到类成员:

在一个未知的dll里面有一个Person类

    public class Person
    {
        private string address;
        private string email;

        public string Name { set; get; }

        public int Age { set; get; }

        public void SayHello()
        {
            Console.WriteLine("你好");
        }

        public static string MystaticPro { set; get; }
        public static void MyStatic()
        {
            Console.WriteLine("我是static方法");
        }
    }

通过反射dll得到Person类

static void Main(string[] args)
        {
            //反射dll
            Type type = typeof(Person);
            //默认得到类下面的所有public成员
            var lstMembers = type.GetMembers();
            foreach (var oMem in lstMembers)
            {
                Console.WriteLine("GetMembers()方法得到的成员名称:" + oMem.Name);
            }
            Console.WriteLine("");

            //默认得到类下面的所有public属性
            var lstProperty = type.GetProperties();
            foreach (var oProp in lstProperty)
            {
                Console.WriteLine("GetProperties()方法得到的成员名称:" + oProp.Name);
            }
            Console.WriteLine("");

            Console.ReadKey();
        }

得到结果

 

(2)反射对象的私有字段:

一般私有属性的用法比较少,我们就以私有字段为例来说明,还是上面的例子:

static void Main(string[] args)
{
    Type type = typeof(Person);
    //默认得到类下面的所有private字段
    var lstField = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
    foreach (var oField in lstField)
    {
        Console.WriteLine("GetFields()方法得到的私有字段名称:" + oField.Name);
    }

    Console.ReadKey();
}

 

(3)反射对象的静态成员:

static void Main(string[] args)
{

    Type type = typeof(Person);
    //默认得到类下面的所有public成员
    var lstMembers = type.GetMembers(BindingFlags.Public | BindingFlags.Static);
    foreach (var oMem in lstMembers)
    {
        Console.WriteLine("GetMembers()方法得到的成员名称:" + oMem.Name);
    }

    Console.ReadKey();
}

还有枚举类型等等就不一一介绍了,基本上都是在BindingFlags这个上面做处理。

 

(4)反射得到对象以及对象的操作:

反射得到对象的方法

        public static T GetModel<T>(T oModel)
        {
            var model = default(T) ;
            
            model = (T)Activator.CreateInstance(typeof(T));
            
            return model;
        }

(5)反射调用方法

static void Main(string[] args)
        {
            Type type = typeof(Person);
            //动态创建类型的实例
            var typeInstance = Activator.CreateInstance(type);
            var methodInfo = type.GetMethod("SayHello", BindingFlags.NonPublic | BindingFlags.Public
                | BindingFlags.Instance | BindingFlags.InvokeMethod);
            if (typeInstance != null)
            {
                if (methodInfo != null)
                {
                    methodInfo.Invoke(typeInstance, null);
                }
            }

            Console.ReadKey();
        }

打印结果,调用SayHello方法

实际项目中的应用

代码是在Unity中实现的,其实,在纯C#环境中,只要把Start方法中的代码放入Main方法中即可。

我们的代码运行在"运行时"为我们创建的AppDomain中,GetAssemblies获取已加载到应用程序域的程序集。

using UnityEngine;
using System;
using System.Reflection;

public class Reflection : MonoBehaviour
{
    //反射是程序可以访问、检测、修改它本身状态或行为一种能力。
    //程序集包括模块,模块包括类型,类型又包括成员。反射可以提供封装程序集、模块和类型的对象。
    //反射可以动态的创建类型的实例,把类型绑定在现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
    void Start()
    {
        //我们的代码运行在"运行时"为我们创建的AppDomain中
        //GetAssemblies获取已加载到应用程序域的程序集。
        Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
        foreach (Assembly assembly in assemblies)
        {
            Type[] types = assembly.GetTypes();
            foreach (Type type in types)
            {
                var customAttribute = type.GetCustomAttributes(typeof(ConvertToBinary), true);
                foreach (var item in customAttribute)
                {
                    var customClass = item as ConvertToBinary;
                    if (customClass == null)
                    {
                        continue;
                    }
                    Type typeC = customClass.m_Type;
                    string methodName = customClass.m_MethodName;
                    if (typeC == null)
                    {
                        Debug.Log("类型为空");
                        continue;
                    }
                    if (string.IsNullOrEmpty(methodName))
                    {
                        Debug.Log(typeC.Name + "方法名为空");
                    }
                    //动态创建类型的实例
                    var typeInstance = Activator.CreateInstance(typeC);
                    var methodInfo = typeC.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Public
                        | BindingFlags.Instance | BindingFlags.InvokeMethod);
                    if (typeInstance != null)
                    {
                        if(methodInfo != null)
                        {
                            methodInfo.Invoke(typeInstance, null);
                        }
                    }
                }
            }
        }
    }
}

 创建一个预定义的特性类ConvertToBinary :

特性:描述运行时传递程序中的各种元素(类、方法、结构体等)行为信息的声明性标签一个特性,是放置在它应用元素的前面的方括号来描述的
预定义特性,AttributeUsage是来描述如何使用一个预定义特性类,第一个参数表示可以使用的语言元素,第二个参数表示多用的
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]

using System;

//特性:描述运行时传递程序中的各种元素(类、方法、结构体等)行为信息的声明性标签
//一个特性,是放置在它应用元素的前面的方括号来描述的
//预定义特性,AttributeUsage是来描述如何使用一个预定义特性类,第一个参数表示可以使用的语言元素,第二个参数表示多用的
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class ConvertToBinary : Attribute
{
    public Type m_Type;
    public string m_MethodName;

    public ConvertToBinary(Type type, string methodName)
    {
        m_Type = type;
        m_MethodName = methodName;
    }
}

给多个class元素应用特性:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ConvertToBinary(typeof(SuitName), "Test1")]
public class SuitName
{
    public List<int> nameList = new List<int>();
    public string id;
    public int num;

    public void Test1()
    {
        Debug.Log("Test1");
    }
}

[ConvertToBinary(typeof(UnityTest), "Test2")]
public class UnityTest
{
    public List<int> list = new List<int>();
    public string id;
    public int num;

    public void Test2()
    {
        Debug.Log("Test2");
    }
}

输出结果,两个测试方法被调用: 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值