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)
        {
            //反射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;
        }
时间: 2024-10-10 09:32:41

C#基础系列——反射笔记的相关文章

C#基础系列 - 反射基础

反射用于在程序运行过程中,获取类里面的信息或发现程序集并运行的一个过程.通过反射可以获得.dll和.exe后缀的程序集里面的信息.使用反射可以看到一个程序集内部的类,接口,字段,属性,方法,特性等信息. 一.各种GetType().typeof的区别 首先就是获取Tyoe对象的来源不同: class Program { static void Main(string[] args) { Type t1 = Type.GetType("ConsoleApplication2.Person"

C#基础系列——再也不用担心面试官问我“事件”了

前言:作为.Net攻城狮,你面试过程中是否遇到过这样的问题呢:什么是事件?事件和委托的区别?既然事件作为一种特殊的委托,那么它的优势如何体现?诸如此类...你是否也曾经被问到过?你又是否都答出来了呢?上两篇由浅及深介绍了下委托的用法,这篇还是来说说事件.希望通过这篇的介绍,博友能有个系统的认识,至少应付面试没问题了吧.不信?瞧瞧去~~ C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序列化效率比拼 C#基础系列——反射笔记 C

C#基础系列——Attribute特性使用

前言:上篇 C#基础系列--反射笔记 总结了下反射得基础用法,这章我们来看看C#的另一个基础技术--特性. 1.什么是特性:就博主的理解,特性就是在类的类名称.属性.方法等上面加一个标记,使这些类.属性.方法等具有某些统一的特征,从而达到某些特殊的需要.比如:方法的异常捕捉,你是否还在某些可能出现异常的地方(例如数据库的操作.文件的操作等)经常使用try...catch.这个时候如果使用特性,就可以大大减少方法里面的try...catch的使用.你只需要定义一个专门捕捉异常的特性类Excepti

C#基础系列——一场风花雪月的邂逅:接口和抽象类

前言:最近一个认识的朋友准备转行做编程,看他自己边看视频边学习,挺有干劲的.那天他问我接口和抽象类这两个东西,他说,既然它们如此相像, 我用抽象类就能解决的问题,又整个接口出来干嘛,这不是误导初学者吗.博主呵呵一笑,回想当初的自己,不也有此种疑惑么...今天打算针对他的问题,结合一个实际的使用场景来说明下抽象类和接口的异同,到底哪些情况需要用接口?又有哪些情况需要用抽象类呢? C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序

C#基础系列——小话泛型

前言:前面两章介绍了C#的两个常用技术:C#基础系列——反射笔记 和 C#基础系列——Attribute特性使用 .这一章来总结下C#泛型技术的使用.据博主的使用经历,觉得泛型也是为了重用而生的,并且大部分时候会和反射一起使用.这次还是打算围绕WWH(即What.Why.How)来讲解. 1.什么是泛型:通过参数化类型来实现在同一份代码上操作多种数据类型.利用“参数化类型”将类型抽象化,从而实现灵活的复用.怎么理解呢,其实根据博主的理解,泛型就是将类型抽象化,使用抽象化的类型或对象去实现某些功能

C#基础系列——异步编程初探:async和await

前言:前面有篇从应用层面上面介绍了下多线程的几种用法,有博友就说到了async, await等新语法.确实,没有异步的多线程是单调的.乏味的,async和await是出现在C#5.0之后,它的出现给了异步并行变成带来了很大的方便.异步编程涉及到的东西还是比较多,本篇还是先介绍下async和await的原理及简单实现. C#基础系列目录: C#基础系列——Linq to Xml读写xml C#基础系列——扩展方法的使用 C#基础系列——序列化效率比拼 C#基础系列——反射笔记 C#基础系列——At

C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)

反射以及Attribute在ORM中的应用 一. 反射什么是反射?简单点吧,反射就是在运行时动态获取对象信息的方法,比如运行时知道对象有哪些属性,方法,委托等等等等.反射有什么用呢?反射不但让你在运行是获取对象的信息,还提供运行时动态调用对象方法以及动态设置.获取属性等的能力.反射在ORM中有什么用呢?我这里所讨论的ORM实现是通过自定义Attribute的方式进行映射规则的描述的.但是我们并不知道具体哪个对象需要对应哪个表,并且这些对象是独立于我们的ORM框架的,所以我们只能通过自定义Attr

黑马程序员_JAVA 基础加强学习笔记

一.面向对象 (一)继承  1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数. 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数. 2.final特点

C#基础系列:开发自己的窗体设计器(PropertyGrid显示中文属性名)

既然是一个窗体设计器,那就应该能够设置控件的属性,设置属性最好的当然是PropertyGrid了,我们仅仅需要使用一个PropertyGrid.SelectedObject = Control就可以搞定,让PropertyGrid显示Control的所有属性.可是这里显示的属性名是英文的.对于我们开发人员来说这无可厚非,我们也乐于接受.并且让PropertyGrid显示中文属性名,这对于我们开发人员的使用来说显得多此一举.可是,对于我这种类型的一个应用工具,英文属性名对于很多客户来说可能就很难懂