C#基础系列——反射笔记

简介:

前言:使用反射也有几年了,但是一直觉得,反这个概念很抽象,今天有时间就来总结下这个知识点。

 

1、为什么需要反射:

  最初使用反射的时候,作为小菜总是不理解,既然可以通过new 一个对象的方式得到对象,然后通过对象去调用属性和方法,那么为什么还需要反射去调用呢?后来使用多了发现这就是一个先绑定还是后绑定的问题,很多初使用反射的开发人员通常都会有类似这种疑虑:既然在开发时就能够写好代码,干嘛还放到运行期去做,不光繁琐,而且效率也受影响。博主觉得主要是适用性的问题,如果你的系统没有那么高的扩展性和灵活性要求,你大可不必考虑反射。但在架构设计时,很多东西都需要考虑复用性,并且在某些特定的场景下你得不到具体的类时,你就必须用到反射。博主总结了下自己使用过的反射场景:

(1)有时不知道具体的类型,可以通过dll去得到类的对象;

(2)某些特殊方法,传过来的是泛型类,需要通过反射处理某些特殊的业务;

(3)通用方法DataTable和List<T>的相互转化时需要用到反射;

 

2、如何使用反射:

(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)
        {
//通过类名称得到类型

        //var assembly = Assembly.Load("Ewin.Client.Web");//参数为程序集的名称
//var oType = assembly.GetType("Ewin.Client.Web.Controllers." + strType);

//反射dll
            var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll");
            var oAssembly = Assembly.LoadFile(strDllPath);
            var lstTypes = oAssembly.GetTypes();
            foreach (var oType in lstTypes)
            {
                if (oType.Name == "Person")
                {
                    //默认得到类下面的所有public成员
                    var lstMembers = oType.GetMembers();
                    foreach (var oMem in lstMembers)
                    {
                        Console.WriteLine("GetMembers()方法得到的成员名称:"+oMem.Name);
                    }
                    Console.WriteLine("");

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

                    //默认得到类下面的所有public字段
                    var lstField = oType.GetFields();
                    foreach (var oField in lstField)
                    {
                        Console.WriteLine("GetFields()方法得到的成员名称:" + oField.Name);
                    }
                }
            }

            Console.ReadKey();
        }
复制代码

得到结果

 

(2)反射对象的私有成员:

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

复制代码
        static void Main(string[] args)
        {
            //反射dll
            var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll");
            var oAssembly = Assembly.LoadFile(strDllPath);
            var lstTypes = oAssembly.GetTypes();
            foreach (var oType in lstTypes)
            {
                if (oType.Name == "Person")
                {
                    //默认得到类下面的所有public字段
                    var lstField = oType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                    foreach (var oField in lstField)
                    {
                        Console.WriteLine("GetFields()方法得到的成员名称:" + oField.Name);
                    }
                }
            }

            Console.ReadKey();
        }
复制代码

 

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

复制代码
        static void Main(string[] args)
        {
            //反射dll
            var strDllPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dll\\ReflectorDLL.dll");
            var oAssembly = Assembly.LoadFile(strDllPath);
            var lstTypes = oAssembly.GetTypes();
            foreach (var oType in lstTypes)
            {
                if (oType.Name == "Person")
                {
                    //默认得到类下面的所有public成员
                    var lstMembers = oType.GetMembers(BindingFlags.Public|BindingFlags.Static);
                    foreach (var oMem in lstMembers)
                    {
                        Console.WriteLine("GetMembers()方法得到的成员名称:" + oMem.Name);
                    }
                    Console.WriteLine("");

                    //默认得到类下面的所有public字段
                    var lstField = oType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
                    foreach (var oField in lstField)
                    {
                        Console.WriteLine("GetFields()方法得到的成员名称:" + oField.Name);
                    }
                }
            }

            Console.ReadKey();
        }
复制代码

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

 

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

反射得到对象的方法主要有两种

复制代码
        public static T GetModel<T>(T oModel)
        {
            var model = default(T) ;
            
            //得到对象的方法一:
            model = (T)typeof(T).GetConstructor(new System.Type[] { }).Invoke(new object[] { });//反射得到泛型类的实体

            //得到对象的方法二:
            model = (T)Activator.CreateInstance(typeof(T));

            //逻辑处理......
            
            return model;
        }
复制代码

对象属性的取值和赋值:

复制代码
        //List集合转换为DataTable
        public static DataTable ListFillTable(object obj)
        {
            if (!(obj is IList))
            {
                return null;
            }
            var objlist = obj as IList;
            if (objlist == null || objlist.Count <= 0)
            {
                return null;
            }
            var tType = objlist[0];
            DataTable dt = new DataTable(tType.GetType().Name);
            DataColumn column;
            DataRow row;
            System.Reflection.PropertyInfo[] myPropertyInfo = tType.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            foreach (var t in objlist)
            {
                if (t == null)
                {
                    continue;
                }
                row = dt.NewRow();
                for (int i = 0, j = myPropertyInfo.Length; i < j; i++)
                {
                    System.Reflection.PropertyInfo pi = myPropertyInfo[i];
                    string name = pi.Name;
                    if (dt.Columns[name] == null)
                    {
                        var coltype = pi.PropertyType;
                        if (coltype.Name == "Nullable`1")
                        {
                            //coltype = typeof(System.DBNull);
                            column = new DataColumn(name);
                        }
                        else
                        {
                            column = new DataColumn(name, coltype);
                        }
                        dt.Columns.Add(column);
                    }
                    row[name] = pi.GetValue(t, null);
                }
                dt.Rows.Add(row);
            }
            return dt;
        }
复制代码





目录
相关文章
|
3月前
|
C# Python
C# 笔记1 - 操作目录
C# 笔记1 - 操作目录
29 0
|
3月前
|
C# Python
C# 笔记3 - 重载一系列像python那样的print()方法
C# 笔记3 - 重载一系列像python那样的print()方法
29 1
|
3月前
|
存储 C# C++
C# 笔记2 - 数组、集合与与文本文件处理
C# 笔记2 - 数组、集合与与文本文件处理
46 0
|
3月前
|
设计模式 C#
C#反射机制实现开闭原则的简单工厂模式
C#反射机制实现开闭原则的简单工厂模式
18 0
|
4月前
|
存储 C# 开发者
C# | 通过反射将对象属性展示在TreeView中
在编程过程中,我们经常需要处理复杂的对象和数据结构。将这些数据结构展示在UI界面上是很有用的,可以帮助开发者更好地理解和分析数据。 而TreeView作为一种常见的控件,可以以树状结构的方式展示数据,非常适合用于展示层次化的对象。 本文将介绍如何使用TreeView控件展示一个对象,并且可以动态处理对象中的属性和子对象。通过本文的学习,您将学会如何更好地理解和展示数据,提高编程效率。
34 0
C# | 通过反射将对象属性展示在TreeView中
|
4月前
|
安全 C# 图形学
C#的反射机制
C#的反射机制
|
5月前
|
存储 Java API
C#反射(Reflection)详解
反射是.NET中的重要机制,通过反射可以得到*.exe或*.dll等程序集内部的接口、类、方法、字段、属性、特性等信息,还可以动态创建出类型实例并执行其中的方法。反射指程序可以访问、检测和修改它本身状态或行为的一种能力。通俗一点:我们在获取其他实体类的字段名或实列,只能获取公有的,而有了反射之后可以获取私有的,可以获取他的基类等等,可以说把家底查得清清楚楚。
31 1
|
7月前
|
开发框架 缓存 安全
C#OOP之十三 组件、程序集与反射
C#OOP之十三 组件、程序集与反射
38 0
|
7月前
|
开发框架 .NET Java
C#下反射动态加载dll后如何卸载?
C#下反射动态加载dll后如何卸载?
|
7月前
|
Oracle 架构师 关系型数据库
C#反射应用之实现动态可配置可扩展框架的简单示例
C#反射应用之实现动态可配置可扩展框架的简单示例