1、简介
Reflection,中文翻译为反射。.Net的应用程序由以下几个部分组成:
a、程序集(assembly)
b、模块(moudle)
c、类型(class)
而通过反射技术可以让程序员在允许期间获取这几个组成部分的关键信息。
2、程序集和命名空间的关系
程序集是.Net应用程序的最小执行单位,通过vs编译工具编译出来的.dll文件就是程序集。
程序集和命名空间的对应关系如下:
a、一个程序集可以包含多个命名空间(命名空间名可以相同,如果命名空间相同,则类似parital关键字的效果)
b、一个命名空间也可以存在于多个程序集中
这里命名空间和类型的关系就不多做说明了
3、反射典型的应用
做过.Net开发的都知道三层模式,其中因为系统可能会存在更换数据库的情况,所以数据层会存在多种类型的情况,如SqlServer版的数据层或者是Oracle的数据层.所以业务层往往会依赖数据层的接口(不会直接和业务层耦合),并通过简单工厂(反射和配置文件)生成对应的数据库实例.
UserBll.cs
using IDal; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Bll { public class UserBll { private IUserDal _userDal; public UserBll() { _userDal = DalFactory.DalMethodFactory.GetUserDal() as IUserDal; } public int AddUser() { return _userDal.AddUser(); } } }
IUserDal.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IDal { public interface IUserDal { int AddUser(); } }
DalMethodFactory.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace DalFactory { public class DalMethodFactory { private readonly const string AssemblyName = "Dal";//可从配置文件中读取 private readonly const string Namespace = "IDal";//可从配置文件中读取
//通过反射创建指定的类型 public static object CreateInstance(string type) { var assembly = Assembly.Load(AssemblyName); return assembly.CreateInstance(Namespace + type); } public static object GetUserDal() { string type =Namespace+".UserDal"; return CreateInstance(type); } } }
UserDal.cs
using IDal; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Dal { public class UserDal:IUserDal { public int AddUser() { return 1; } } }
以上就是反射典型的应用.
3、反射常用的类型-System.Type类
(1)、Type是一个抽象类,当实例化了一个Type实例,实际上是实例化了一个Type的派生类。Type有与每种数据类型对应的派生类,它们一般不会添加新的方法或属性。获取任何给定类型的Type有三种方式:
a、通过typeof关键字
Type t=typeof(Test);
b、通过Object的实例方法GetType()
Type t=New Test().GetType();
c、通过Type的GetType()静态方法
Type t = Type.GetType("RnLn.Test");
(2)、Type的属性和方法介绍
Type是许多反射功能的入口,它实现许多方法和属性,这里不可能一一列举,只介绍一些常用的,主要介绍如何使用这个类。
注:Type的属性都是只读的,可以它们确定数据的类型,但是不能对它们进行修改.
属性:
a、Name ---数据类型名
string str = "yes"; Type t = str.GetType(); Console.WriteLine(t.Name);
b、FullName ---数据类型的完全限定名(不包括程序集)
string str = "yes"; Type t = str.GetType(); Console.WriteLine(t.FullName);
c、Namespace ---数据类型的命名空间
d、Module ---获取定义定义数据类型所在的dll程序集或者是.exe程序
Type t = new Test().GetType(); Console.WriteLine(t.Module);
e、BaseType ---数据类型的"最近"基类型
Type t = new Test().GetType(); Console.WriteLine(t.BaseType);
f、UnderlyingSystemType ---数据类型在.Net运行库中映射到的类型
Type t = new Test().GetType(); Console.WriteLine(t.UnderlyingSystemType);
g、IsXXX系列
IsAbstract(判断数据类型是否是抽象)、IsArray(是否为数组)、IsClass(是否为类)、IsEnum(是否为枚举)
方法:
System.Type的大多数方法用于获取对应数据类型的成员信息:构造函数、方法、属性和事件等。
a、GetMethods() 获取指定数据类型的所有的公共方法,有两个构造函数
参数:BindingFlags ---类型搜索方法的标志。按照BindingFlags指定的规则去搜索指定类型的成员和方法.具体请参考MSDN
返回值:返回一个MethodInfo[]数组
class Program { static void Main(string[] args) { Type t = new Test().GetType(); MethodInfo[] methods=t.GetMethods();//获取Test类型的所有公共方法 StringBuilder sb = new StringBuilder(); for(int i=0;i<methods.Length;i++) { sb.Append("第" + (i + 1) + "个方法:"); sb.Append(methods[i].Name); sb.AppendLine(); } Console.WriteLine(sb.ToString()); } } public class Test { public Test() { } public void Method1() {} public void Method2() {} public static void Method3() {} }
b、GetMthod() ---按照参数,获取数据类型的指定的方法
参数:
Name ---要获取的公共方法的名称
BindingFlags ---类型搜索方法的标志。按照BindingFlags指定的规则去搜索指定类型的成员和方法.具体请参考MSDN
Binder ---派生自定义的Binder类型,它可以几乎完全控制反射的工作方式(这里用几乎,是因为它受到了RuntimeType 实现时的一些限制)默认情况下使用的 System.DefaultBinder 类已经足够的使用了,因此不用太过于在意这个参数。