先来一段有用的反射代码

namespace Calculator
{
public interface Iwel
{
String Print();
}
} namespace Calculator
{
public class Arithmetic:Iwel
{
/// <summary>
/// 没有带参数的构造函数
/// </summary>
public Arithmetic()
{}
public Arithmetic(int num1, int num2)
{
_num1 = num1;
_num2 = num2;
}
private int _num1; public int Num1
{
get { return _num1; }
set { _num1 = value; }
}
private int _num2; public int Num2
{
get { return _num2; }
set { _num2 = value; }
}
public String Add(int num1, int num2)
{
Console.WriteLine("{0}+{1}={2}", num1, num2, num1 + num2);
return "Add(int num1,int num2)方法是一个公有的带参数的方法";
}
private string Add()
{
return "Add()方法是一个私有的不传参数的方法";
}
private void Subtration(int num1, int num2)
{
Console.WriteLine("{0}-{1}={2}+Subtration(int num1,int num2)" + "方法是一个私有的带有参数的方法 ",num1,num2,num1-num2);
}
public static void Multiplication(int num1, int num2)
{
Console.WriteLine("{0}*{1}={2} Multiplication(int num1,int num2)"+"是一个公有的带参数的静态方法",num1,num2,num1+num2);
}
private static void Multiplication()
{
Console.WriteLine("Multiplication()是一个公有的带参数的静态方法"); }
public String Writ()
{
return "Writ() 是一个公有的不带参数的方法";
}
#region Iwel 成员 public string Print()
{
return "欢迎您使用接口!";
} #endregion }
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection; namespace BassLib
{
class Program
{ delegate void TestDelegate(int num1, int num2);
static void Main(string[] args)
{
Assembly assembly = Assembly.Load("Calculator");//加载程序集
Console.WriteLine("得到Calculator.dll中的所有类");
Console.WriteLine("***********************************");
foreach (Type myType in assembly.GetTypes())
{
//得到Calculator.dll中所有的类
Console.WriteLine(myType.Name + "是Calculator命中空间下的类");
}
Console.WriteLine(" +++++++++++++++++++++++++++++++++++++");
Console.WriteLine("得到Calculator.dll中的模块集");
Module[] modules = assembly.GetModules();//得到Calculator.dll中的模块集合
foreach (Module module in modules)
{
Console.WriteLine(module.Name + "是Calculator中的一个模块 ");
}
Console.WriteLine("*********************************************");
Console.WriteLine(""); Type type = typeof(Calculator.Arithmetic);//得到具体的类型
Console.WriteLine("具体的类型是" + type.Name);
Console.WriteLine(" {0}是不是public类型:{1}", type, type.IsPublic);
Console.WriteLine("{0}是不是private类型:{1}", type, type.IsNotPublic); Console.WriteLine("*********************************************");
Console.WriteLine("");
PropertyInfo[] memberInfo = type.GetProperties();//得到类中的属性
foreach (PropertyInfo var in memberInfo)
{
Console.WriteLine(type + "类的属性有" + var.Name);
}
Console.WriteLine("**********************************************");
Console.WriteLine(""); Type[] t = type.GetInterfaces();//得到接口
foreach (Type var in t)
{
Console.WriteLine(var.Name + "是Calculator.dll中的接口");
}
Console.WriteLine("*****************************************");
Console.WriteLine(""); Console.WriteLine("方法的返回类型,方法传参的类型");
//查找私有的方法
MethodInfo[] method = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic);
foreach (MemberInfo var in method)
{
Console.WriteLine("私有方法: 方法名 ={0} 方法的信息={1}", var.Name, var);
}
//查找公有方法
MethodInfo[] methodpublic = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
foreach (MethodInfo var in methodpublic)
{
Console.WriteLine("公有方法:方法名={0} 方法的信息={1}", var.Name, var);
}
//查找公有的静态方法
MethodInfo[] mathodstatic = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
foreach (MethodInfo var in mathodstatic)
{
Console.WriteLine("公有静态方法: 方法名={0} 方法的信息 ={1}", var.Name, var);
}
//查找私有静态方法
MethodInfo[] methodprivartstatic = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static);
foreach (MethodInfo var in methodprivartstatic)
{
Console.WriteLine("私有静态方法: 方法名={0} 方法的信息={1}", var.Name, var);
}
Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++");
Console.WriteLine("这是一个构造方法的形式 "); ConstructorInfo[] con = type.GetConstructors();//获得构造函数的形式
foreach (ConstructorInfo var in con)
{
Console.WriteLine(var);
}
Console.WriteLine("_________________________________");
object obj = Activator.CreateInstance(type, null);//创建了一个不带参数的实例
//公有非静态带参数和返回参数的方法的调用它
MethodInfo men1 = type.GetMethod("Add");
Console.WriteLine("调用{0}方法 ", men1);
object[] nums1 = { , };//参数
Console.WriteLine(men1.Invoke(obj, nums1)); Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
//私有的非静态方法的调用
MethodInfo men2 = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic);
Console.WriteLine(men2.Invoke(obj, null));
Console.WriteLine("**********************************");
//公有的静态带参数的方法的调用
MethodInfo men3 = type.GetMethod("Multiplication", BindingFlags.Public | BindingFlags.Static);
object[] nums2 = { , };
men3.Invoke(null, nums2);
Console.WriteLine("*****************");
//私有的静态的
MethodInfo men4 = type.GetMethod("Multiplication", BindingFlags.NonPublic | BindingFlags.Static);
men4.Invoke(null, null);
Console.WriteLine("************************");
//动态创建一个委托
Console.WriteLine("动态创建委托");
TestDelegate dele = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "Subtration");
dele(, );
}
}
}

反射的几种基本类型

1、System.Reflection.Assembly类

通过Assembly可以动态加载程序集,并查看程序集的内部信息,其中最常用的就是Load()这个方法。

Assembly assembly=Assembly.Load("MyAssembly");

利用Assembly的object CreateInstance(string) 方法可以反射创建一个对象,参数0为类名。

2、System.Type类

Type是最常用到的类,通过Type可以得到一个类的内部信息,也可以通过它反射创建一个对象。一般有三个常用的方法可得到Type对象。

  1. 利用typeof() 得到Type对象

    Type type=typeof(Example);

  2. 利用System.Object.GetType() 得到Type对象

    Example example=new Example();

    Type type=example.GetType();

  3. 利用System.Type.GetType() 得到Type对象

    Type type=Type.GetType("MyAssembly.Example",false,true);

    注意参数0是类名,参数1表示若找不到对应类时是否抛出异常,参数1表示类名是否区分大小写

例子:

我们最常见的是利用反射与Activator结合来创建对象:

Assembly assembly= Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);

3、反射方法

1.通过 System.Reflection.MethodInfo能查找到类里面的方法

代码:

Type type=typeof(Example);
MethodInfo[] listMethodInfo=type.GetMethods();
foreach(MethodInfo methodInfo in listMethodInfo)
Cosole.WriteLine("Method name is "+methodInfo.Name);

2.我们也能通过反射方法执行类里面的方法

代码:

Assembly assembly= Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);
MethodInfo methodInfo=type.GetMethod("Hello World"); //根据方法名获取MethodInfo对象
methodInfo.Invoke(obj,null); //参数1类型为object[],代表Hello World方法的对应参数,输入值为null代表没有参数

4、反射属性

1.通过 System.Reflection.PropertyInfo 能查找到类里面的属性

常用的方法有GetValue(object,object[]) 获取属性值和 SetValue(object,object,object[]) 设置属性值

代码:

Type type=typeof(Example);
PropertyInfo[] listPropertyInfo=type.GetProperties();
foreach(PropertyInfo propertyInfo in listPropertyInfo)
Cosole.WriteLine("Property name is "+ propertyInfo.Name);

2.我们也可以通过以下方法设置或者获取一个对象的属性值

代码:

Assembly assembly=Assembly.Load("MyAssembly");
Type type=assembly.GetType("Example");
object obj=Activator.CreateInstance(type);
PropertyInfo propertyInfo=obj.GetProperty("Name"); //获取Name属性对象
var name=propertyInfo.GetValue(obj,null); //获取Name属性的值
PropertyInfo propertyInfo2=obj.GetProperty("Age"); //获取Age属性对象
propertyInfo2.SetValue(obj,,null); //把Age属性设置为34

5、反射字段

通过 System.Reflection.FieldInfo 能查找到类里面的字段

它包括有两个常用方法SetValue(object ,object )和GetValue(object)  因为使用方法与反射属性非常相似,在此不再多作介绍

6、反射特性

通过System.Reflection.MemberInfo的GetCustomAttributes(Type,bool)就可反射出一个类里面的特性,以下例子可以反射出一个类的所有特性

代码:

Type type=typeof("Example");
object[] typeAttributes=type.GetCustomAttributes(false); //获取Example类的特性
foreach(object attribute in typeAttributes)
Console.WriteLine("Attributes description is "+attribute.ToString());

通过下面例子,可以获取Example类Name属性的所有特性

代码:

public class Example
{
[DataMemberAttribute]
publics string Name
{get;set;}
..................
} Type type = typeof(Example);
PropertyInfo propertyInfo=type.GetProperty("Name"); //获取Example类的Name属性
foreach (object attribute in propertyInfo.GetCustomAttributes(false)) //遍历Name属性的所有特性
Console.WriteLine(“Property attribute: "+attribute.ToString());

7、反射成员

我们先考虑一下对于一个类型Type,可能会包含什么类型,常见的有字段、属性、方法、构造函数、接口、嵌套类型等。MemberInfo 类代表着 Type的成员类型,值得注意的是Type类本身又继承自MemberInfo类,理解起来并不困难,因为一个类型经常也是另一类型的成员。Type类提供 GetMembers()、GetMember()、FindMember()等方法用于获取某个成员类型。

我们再添加一个方法 MemberExplore(),来查看一个类型的所有成员类型。

namespace Demo
{

    class SimpleExplore

    {

        static void Main(string[] args)

        {

            MemberExplore(typeof(DemoClass));

        }

 

        public static void MemberExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            MemberInfo[] memberInfo = t.GetMembers();

            sb.Append("查看类型 " + t.Name + "的成员信息:\n");

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");

            }

            Console.WriteLine(sb.ToString());

        }

    }

}

产生的输出如下:

我们使用了GetMembers()方法获取了成员信息的一个数组,然后遍历了数组,打印了成员的名称和类型。如同我们所知道的:Name属性在编译后成为了get_Name()和set_Name()两个独立的方法;myEvent事件的注册(+=)和取消注册(-=)分别成为了add_myEvent()和remove_myEvent方法。同时,我们发现私有(private)字段name 没有被打印出来,另外,基类System.Object的成员GetType()和Equals()也被打印了出来。

有的时候,我们可能不希望查看基类的成员,也可能希望查看私有的成员,此时可以使用GetMembers()的重载方法,传入BindingFlags 位标记参数来完成。BindingFlags位标记对如何获取成员的方式进行控制(也可以控制如何创建对象实例,后面会说明)。对于本例,如果我们想获取所有的公有、私有、静态、实例成员,那么只需要这样修改GetMembers()方法就可以了。

public static void MemberExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            //MemberInfo[] memberInfo = t.GetMembers();

            MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static

                | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            sb.Append("查看类型 " + t.Name + "的成员信息:\n");

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");

            }

            Console.WriteLine(sb.ToString());

        }

此时的输出如下:

可以看到,继承自基类 System.Object 的方法都被过滤掉了,同时,打印出了私有的 name, myEvent 等字段。

现在如果我们想要获取所有的方法(Method),那么我们可以使用 Type类的FindMembers()方法:

public static void MemberExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

 

            //MemberInfo[] memberInfo = t.GetMembers();

 

            //MemberInfo[] memberInfo = t.GetMembers(BindingFlags.Public | BindingFlags.Static

            //    | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);

 

            MemberInfo[] memberInfo = t.FindMembers(MemberTypes.Method, // 说明查找的成员类型为 Method 

                                    BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic

                                    | BindingFlags.Instance | BindingFlags.DeclaredOnly, Type.FilterName, "*");

 

            sb.Append("查看类型 " + t.Name + "的成员信息:\n");

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append("成员:" + mi.ToString().PadRight(40) + " 类型: " + mi.MemberType + "\n");

            }

            Console.WriteLine(sb.ToString());

        }

Type.FilterName 返回一个MemberFilter类型的委托,它说明按照方法名称进行过滤,最后一个参数“*”,说明返回所有名称(如果使用“Get*”,则会返回所有以Get开头的方法)。

现在的输出如下:

MemberInfo 类有两个属性值得注意,一个是DeclaringType,一个是 ReflectedType,返回的都是Type类型。DeclaredType 返回的是声明该成员的类型。比如说,回顾我们之前的一段代码:

MemberInfo[] members = typeof(DemoClass).GetMembers();

它将返回所有的公有成员,包括继承自基类的Equals()等方法,对于Equals()方法来说,它的 DeclaringType 返回的是相当于 typeof(Object) 的类型实例,因为它是在 System.Object中被定义的;而它的ReflectedType 返回的则是相当于 typeof(DemoClass) 类型实例,因为它是通过 DemoClass 的类型实例被获取的。

C#秘密武器之反射——基础篇的更多相关文章

  1. C#秘密武器之反射——替换反射

    反射虽然有时很有必要,但是应用反射的代码大多“复杂难懂”.“性能不高”,因此我们可以找寻在一些场景下替换反射的方法.此处也只是一些栗子,更多巧妙的应用还是自己以后亲自查查~ 先来看看一个使用普通反射完 ...

  2. C#秘密武器之多线程——基础

    多线程概述 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是程序中的一个执行流,每个线程 ...

  3. 转:.NET基础篇——反射的奥妙

    反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等程序集内部的信息.使用反射可以看到一个程序集内部的接口.类.方法.字段.属性.特性等等信息.在System.Reflectio ...

  4. TypeScript: Angular 2 的秘密武器(译)

    本文整理自Dan Wahlin在ng-conf上的talk.原视频地址: https://www.youtube.com/watch?v=e3djIqAGqZo 开场白 开场白主要分为三部分: 感谢了 ...

  5. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

  6. margin负值 – 一个秘密武器

    CSS盒模型中,margin是我们老熟悉的一个属性了, 它的负值你用过吗? 你知道 margin负值的秘密武器吗?我们一起看看吧! 1.带竖线分隔的横向列表(例如:网站底部栏目) 传统的分隔符是使用 ...

  7. DDD分层架构之领域实体(基础篇)

    DDD分层架构之领域实体(基础篇) 上一篇,我介绍了自己在DDD分层架构方面的一些感想,本文开始介绍领域层的实体,代码主要参考自<领域驱动设计C#2008实现>,另外参考了网上找到的一些示 ...

  8. Python 经典面试题汇总之基础篇

    基础篇 1:为什么学习Python 公司建议使用Python,然后自己通过百度和向有学过Python的同学了解了Python.Python这门语言,入门比较简单,它简单易学,生态圈比较强大,涉及的地方 ...

  9. Java面试题之基础篇概览

    Java面试题之基础篇概览 1.一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,且public的类名必须与文件名相一致. 2.Ja ...

随机推荐

  1. solr requestHandler

    使用哪一个handler: 1. 可以通过在url中追加有名字的handler(以 ' / ' 开头命名)的名称来指定使用哪一个handler. 如: <requestHandler name= ...

  2. python接口自动化11-post传data参数案例【转载】

    前言: 前面登录博客园的是传json参数,有些登录不是传json的,如jenkins的登录,本篇以jenkins登录为案例,传data参数. 一.登录jenkins抓包 1.登录jenkins,输入账 ...

  3. Django基本操作

    Django官网下载页面 安装(安装最新LTS版): pip3 install django==1.11.9 创建一个django项目: 下面的命令创建了一个名为"s8"的Djan ...

  4. MVC架构中的controller的几种写法

    开始写代码之前,我们先来看一下spring MVC概念.一张图能够清晰得说明. 除了controller,我们需要编写大量代码外,其余的都可以通过配置文件直接配置. MVC的本质即是将业务数据的抽取和 ...

  5. Iphone安装Pinterest

    由于Pinterest在中国的app store下架了,也就搜索不到该应用.所以只能上美国的app store下载. 1,下载itunes,登录vpn,注册新的apple id: 2,手机连接vpn, ...

  6. docker的存储结构,和以前有了很大不同

    在网上学习这一块知识点时,有一个URL讲得很详细, docker 镜像与容器存储目录结构精讲 http://blog.csdn.net/wanglei_storage/article/details/ ...

  7. Undefined index: validate(thinkphp)

    今天在用thinkphp3.23时发现错误 NOTIC: [8] Undefined index: validate  此处是thinkphp核心目录\Think\Model.class.php 第 ...

  8. Problem C: #104. 普通平衡树

    #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #inc ...

  9. IntelliJ IDEA 常用设置/快捷键

    经常用到 IntelliJ IDEA 编写java,由于不时需要重装系统,所以Mark一下一些基本的设置选项,以便查询,这篇帖子会一直更新,只要有常用的新的设置或者快捷键 一.常用设置 显示代码行号 ...

  10. 线程同步CriticalSection

    孙鑫 第十五/十六课之四 线程同步CriticalSection 说明 在使用多线程时,一般很少有多个线程完全独立的工作.往往是多个线程同时操作一个全局变量来获取程序的运行结果.多个线程同时访问同一个 ...