C#教程之自己动手写映射第三节[反射]
2012-07-24 03:01
531 查看
一、什么是反射
MSND:反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
实用概念:反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射。
反射的名称空间:System.Reflection,具体参考 http://msdn.microsoft.com/zh-cn/library/system.reflection.aspx
二、利用反射动态创建类的实例
前置条件:我们创建两个项目来展示反射的简单应用
CSharp.Model:类库,Employee.cs,我们要反射的测试实体类。
CSharp.Reflection:控制台应用程序项目,Program.cs为主程序类,App.config配置文件,配置我们要反射的程序集的名称,Constant.cs用于调用配置文件的常量类。
CSharp.Model.Employee代码如下:
CSharp.Reflection的配置文件与常量类代码如下:
CSharp.Reflection的主程序类代码如下:
通过上面的示例可以看出,平时我们在创建对象的时候是通过 Employee employee = new Employee(); 来创建。而应用了反射后,我们通过方法System.Reflection.Assembly.Load("程序集名称").CreateInstance("类型名称");在运行时动态的创建类的实例。
上面的实例中我用了两个方法,主要是强调下反射中Load的是程序集,如上示例employee的实例创建,实际上反射的是已经被我们编译好的,存在于bin目录下的CSharp.Model.dll。而employeeNew我们用的方法是LoadFile,其实原理是一样的,只不过这个方法我们提供的是物理地址。
CreateInstance("类型名称")中的"类型名称"一定要为类的全名,即:"名称空间"+"类名"。
反射出来的为Object对象,我们在使用的时候要进行类型转换,如上例所示(Employee)Assembly.Load......
运行效果如下图所示:
![](http://pic002.cnblogs.com/images/2012/414533/2012072322193994.jpg)
三、利用反射动创建类
动态创建类:通过字符串描述类的结构,然后由.net编辑器编辑成类文件,如有必要还可以编辑成.dll的一个动态使用类的过程。
首先我们先进行类的描述,在很多框架中XML是类描述的主要文件类型,这里我们也不例外,为了简单起见我在本例中用了App.config文件来描述类。
前置条件:
CSharp.Dynamic:控制台应用程序,Program.cs为主程序类,App.config用于描述类的结构,Constant.cs读取配置文件的常量类。
CSharp.Dynamic的配置文件与常量类代码如下:
CSharp.Dynamic的主程序类代码如下:
我们在App.config中定义了Employee类的结构,通过string ClassDefined = Constant.CLASSDEFINED;把字符串引用到程序中,并进行一系统的处理。
反射创建类的步骤如下:
用字符串定义类的结构。
创建代码编译器并编译。
获取编译后的程序集并反射出类的对象和类型。
属性、方法、事件等......赋值。
使用属性、方法、事件等......。
如果编译参数设置成内存输入[paras.GenerateInMemory = true;],则由.net 内存回收托管,否则在Temp[C:\Users\Administrator\AppData\Local\Temp]文件夹中产生临时文件"随机字符.dll",每运行一次该程序都将会产生一个新的DLL。
在上例中,除了导入了System.Reflection名称空间外还导入了System.CodeDom.Compiler与Microsoft.CSharp。
System.CodeDom.Compiler:支持编程语言的源代码的生成和编译进行管理。具体参考:http://msdn.microsoft.com/zh-cn/library/z6b99ydt
Microsoft.CSharp:编译和生成代码,名称空间下只有一个类CSharpCodeProvider。具体参考:http://msdn.microsoft.com/zh-cn/library/microsoft.csharp.aspx
设置属性:employee.GetProperty("ID").SetValue(dynamicClass, 1, null);
读取属性:employee.GetProperty("Name").GetValue(dynamicClass, null);
执行方法:employee.GetMethod("Method").Invoke(dynamicClass, new object[] { "员工编号:" });
上面的三个方法中的employee为类型,dynamicClass对象的实例。
运行效果如下图所示:
![](http://pic002.cnblogs.com/images/2012/414533/2012072402483435.jpg)
四、总结
反射在实际应用中还是比较广泛的,从设计模式的典型"抽象工厂模式"到我们平时应用到的"框架",都会用到反射,其原理大多是动态创建类,如:根据数据库的字段动态生成类,执行些方法等等。为了在介绍"C#教程之自己动手写映射"的课程,这里我只对反射常用的方法进行了讲解,如果感兴趣的话可查看MSND继续研究。
五、源码下载
06CSharp映射教程_03.rar
六、版权
转载请注明出处:http://www.cnblogs.com/iamlilinfeng
MSND:反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。
实用概念:反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射。
反射的名称空间:System.Reflection,具体参考 http://msdn.microsoft.com/zh-cn/library/system.reflection.aspx
二、利用反射动态创建类的实例
前置条件:我们创建两个项目来展示反射的简单应用
CSharp.Model:类库,Employee.cs,我们要反射的测试实体类。
CSharp.Reflection:控制台应用程序项目,Program.cs为主程序类,App.config配置文件,配置我们要反射的程序集的名称,Constant.cs用于调用配置文件的常量类。
CSharp.Model.Employee代码如下:
/* * * 创建人:李林峰 * * 时 间:2012-7-23 * * 描 述:反射类的实例 * */ using System; using System.Collections.Generic; using System.Text; namespace CSharp.Model { /// <summary> /// 员工类 /// </summary> public class Employee { public int ID { get; set; } //编号 public string Name { get; set; } //姓名 public string Password { get; set; } //密码 public string Department { get; set; } //部门 public string Position { get; set; } //职位 /// <summary> /// 测试方法 /// </summary> /// <returns></returns> public string Method() { return this.ID.ToString(); } } }
CSharp.Reflection的配置文件与常量类代码如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <!--程序集名称--> <add key="AssemblyName" value="CSharp.Model"></add> </appSettings> </configuration> /* * * 创建人:李林峰 * * 时 间:2012-7-23 * * 描 述:常量类 * */ using System.Configuration; namespace CSharp.Reflection { class Constant { /// <summary> /// 程序集名称 /// </summary> public static string ASSEMBLYNAME = ConfigurationManager.AppSettings["AssemblyName"]; } }
CSharp.Reflection的主程序类代码如下:
/* * * 创建人:李林峰 * * 时 间:2012-7-23 * * 描 述:应用程序入口 * */ using System.Reflection;//反射的名称空间 using CSharp.Model; //实体名称空间 namespace CSharp.Reflection { class Program { static void Main(string[] args) { Employee employee = (Employee)Assembly.Load(Constant.ASSEMBLYNAME).CreateInstance("CSharp.Model.Employee"); employee.ID = 1; employee.Name = "李林峰"; employee.Department = "技术"; employee.Position = "程序员"; System.Console.WriteLine(employee.Name); System.Console.WriteLine(employee.Department); System.Console.WriteLine(employee.Position); System.Console.WriteLine(employee.Method()); System.Console.WriteLine("---------------------------------"); Employee employeeNew = (Employee)Assembly.LoadFile(@"E:\公司内网\HZYT.Test\06 C#映射教程\ClassThree\CSharp.Reflection\bin\Debug\CSharp.Model.dll").CreateInstance("CSharp.Model.Employee"); employee.ID = 2; employeeNew.Name = "李林峰"; employeeNew.Department = "技术"; employeeNew.Position = "程序员"; System.Console.WriteLine(employeeNew.Name); System.Console.WriteLine(employeeNew.Department); System.Console.WriteLine(employeeNew.Position); System.Console.WriteLine(employee.Method()); } } }
通过上面的示例可以看出,平时我们在创建对象的时候是通过 Employee employee = new Employee(); 来创建。而应用了反射后,我们通过方法System.Reflection.Assembly.Load("程序集名称").CreateInstance("类型名称");在运行时动态的创建类的实例。
上面的实例中我用了两个方法,主要是强调下反射中Load的是程序集,如上示例employee的实例创建,实际上反射的是已经被我们编译好的,存在于bin目录下的CSharp.Model.dll。而employeeNew我们用的方法是LoadFile,其实原理是一样的,只不过这个方法我们提供的是物理地址。
CreateInstance("类型名称")中的"类型名称"一定要为类的全名,即:"名称空间"+"类名"。
反射出来的为Object对象,我们在使用的时候要进行类型转换,如上例所示(Employee)Assembly.Load......
运行效果如下图所示:
![](http://pic002.cnblogs.com/images/2012/414533/2012072322193994.jpg)
三、利用反射动创建类
动态创建类:通过字符串描述类的结构,然后由.net编辑器编辑成类文件,如有必要还可以编辑成.dll的一个动态使用类的过程。
首先我们先进行类的描述,在很多框架中XML是类描述的主要文件类型,这里我们也不例外,为了简单起见我在本例中用了App.config文件来描述类。
前置条件:
CSharp.Dynamic:控制台应用程序,Program.cs为主程序类,App.config用于描述类的结构,Constant.cs读取配置文件的常量类。
CSharp.Dynamic的配置文件与常量类代码如下:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="ClassDefined" value="namespace CSharp.Dynamic{ public class Employee{ public int ID { get; set; } public string Name { get; set; } public string Department { get; set; } public string Position { get; set; } public string Method(string parm){return parm+this.ID.ToString();} }}"/> </appSettings> </configuration> /* * * 创建人:李林峰 * * 时 间:2012-7-23 * * 描 述:常量类 * */ using System.Configuration; namespace CSharp.Dynamic { class Constant { /// <summary> /// 程序集名称 /// </summary> public static string CLASSDEFINED = ConfigurationManager.AppSettings["ClassDefined"]; } }
CSharp.Dynamic的主程序类代码如下:
/* * * 创建人:李林峰 * * 时 间:2012-7-23 * * 描 述:利用反射动创建类实例 * */ using System; using System.CodeDom.Compiler; using Microsoft.CSharp; using System.Reflection; namespace CSharp.Dynamic { class Program { static void Main(string[] args) { //在App.Config中读取类的定义字符串 string ClassDefined = Constant.CLASSDEFINED; //创建代码编译器 CSharpCodeProvider codeProvider = new CSharpCodeProvider(); //设置编译参数 CompilerParameters paras = new CompilerParameters(); //设置在内存中生成输出。 paras.GenerateInMemory = true; //编译代码 CompilerResults result = codeProvider.CompileAssemblyFromSource(paras, ClassDefined); //获取编译后的程序集 Assembly assembly = result.CompiledAssembly; //获取反射出来的对象 Object dynamicClass = assembly.CreateInstance("CSharp.Dynamic.Employee"); //获取员工实例的类型 Type employee = dynamicClass.GetType(); //设置属性 employee.GetProperty("ID").SetValue(dynamicClass, 1, null); employee.GetProperty("Name").SetValue(dynamicClass, "李林峰", null); employee.GetProperty("Department").SetValue(dynamicClass, "技术部", null); employee.GetProperty("Position").SetValue(dynamicClass, "程序员", null); //读取属性 string Name = employee.GetProperty("Name").GetValue(dynamicClass, null).ToString(); string Department = employee.GetProperty("Department").GetValue(dynamicClass, null).ToString(); string Position = employee.GetProperty("Position").GetValue(dynamicClass, null).ToString(); //执行方法 string ParmAndID = employee.GetMethod("Method").Invoke(dynamicClass, new object[] { "员工编号:" }).ToString(); //输出 Console.WriteLine(Name); Console.WriteLine(Department); Console.WriteLine(Position); Console.WriteLine(ParmAndID); } } }
我们在App.config中定义了Employee类的结构,通过string ClassDefined = Constant.CLASSDEFINED;把字符串引用到程序中,并进行一系统的处理。
反射创建类的步骤如下:
用字符串定义类的结构。
创建代码编译器并编译。
获取编译后的程序集并反射出类的对象和类型。
属性、方法、事件等......赋值。
使用属性、方法、事件等......。
如果编译参数设置成内存输入[paras.GenerateInMemory = true;],则由.net 内存回收托管,否则在Temp[C:\Users\Administrator\AppData\Local\Temp]文件夹中产生临时文件"随机字符.dll",每运行一次该程序都将会产生一个新的DLL。
在上例中,除了导入了System.Reflection名称空间外还导入了System.CodeDom.Compiler与Microsoft.CSharp。
System.CodeDom.Compiler:支持编程语言的源代码的生成和编译进行管理。具体参考:http://msdn.microsoft.com/zh-cn/library/z6b99ydt
Microsoft.CSharp:编译和生成代码,名称空间下只有一个类CSharpCodeProvider。具体参考:http://msdn.microsoft.com/zh-cn/library/microsoft.csharp.aspx
设置属性:employee.GetProperty("ID").SetValue(dynamicClass, 1, null);
public virtual void SetValue( Object obj, Object value, Object[] index ) 参数 obj 类型:System.Object 将设置其属性值的对象。 value 类型:System.Object 此属性的新值。 index 类型:System.Object[] 索引化属性的可选索引值。 对于非索引化属性,该值应为 null。
读取属性:employee.GetProperty("Name").GetValue(dynamicClass, null);
public virtual Object GetValue( Object obj, Object[] index ) 参数 obj 类型:System.Object 将返回其属性值的对象。 index 类型:System.Object[] 索引化属性的可选索引值。 对于非索引化属性,该值应为 null。 返回值 类型:System.Object obj 参数指定的对象的属性值。
执行方法:employee.GetMethod("Method").Invoke(dynamicClass, new object[] { "员工编号:" });
public Object Invoke( Object obj, Object[] parameters ) 参数 obj 类型:System.Object 实体对象。 Object[] parameters 类型:System.Object[] 参数数组,如果参数为空,该值应为 null。 返回值 类型:System.Object obj 参数指定的对象的属性值。
上面的三个方法中的employee为类型,dynamicClass对象的实例。
运行效果如下图所示:
![](http://pic002.cnblogs.com/images/2012/414533/2012072402483435.jpg)
四、总结
反射在实际应用中还是比较广泛的,从设计模式的典型"抽象工厂模式"到我们平时应用到的"框架",都会用到反射,其原理大多是动态创建类,如:根据数据库的字段动态生成类,执行些方法等等。为了在介绍"C#教程之自己动手写映射"的课程,这里我只对反射常用的方法进行了讲解,如果感兴趣的话可查看MSND继续研究。
五、源码下载
06CSharp映射教程_03.rar
六、版权
转载请注明出处:http://www.cnblogs.com/iamlilinfeng
相关文章推荐
- C#教程之自己动手写映射第四节[封装删除]
- C#教程之自己动手写映射第六节[封装列表]
- C#教程之自己动手写映射第五节[封装添加]
- C#教程之自己动手写映射第七节[总结与代码下载]
- C#教程之自己动手写映射第二节[实例]
- C#教程之自己动手写映射第一节[动机]
- 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
- 自己动手写中文分词解析器完整教程,并对出现的问题进行探讨和解决(附完整c#代码和相关dll文件、txt文件下载)
- 通俗易懂的C#之反射教程
- C#中的反射入门知识教程
- 自己动手写Redis客户端(C#实现)3 - GET请求和批量回复
- 自己动手用c#写控件(上)
- C#基础系列:实现自己的ORM(反射以及Attribute在ORM中的应用)
- 自己动手不求人 - 手工Ghost安装xp、win7系统教程
- C# 反射/映射学习
- 自己动手写ORM框架(四):关系映射配置—Id属性
- 自己动手用c#写控件
- C#根据反射和特性实现ORM映射实例分析
- 自己动手用c#写控件(下)
- C# 反射只获取自己定义的属性,不获取父类的属性