C#类型反射、晚期绑定、特性编程的使用背景与分析
2012-06-12 14:32
776 查看
任何编程语言的任何特点都是有存在的道理的,C#中有些特点也许我们不求甚解的用过,但是如果知道它的使用背景与原理,使用起来将更加得心应手。本文主要分析的就是C#中的类型反射、晚期绑定、特性编程。阐释为什么要用这些语言特点?
首先看一下简单项目的需求:程序员开发了很多模块,每个模块对应相应的功能,不同的用户可能需要使用的模块不一样,模块以插件的形式与系统集成,也就是提供给用户一个自定义模块的功能。
更加形象的比如:一个通用的图书馆里系统中有普通老师模块、有院长模块、有校长模块、有学生模块,这些模块都具有借书的功能(每个模块借书本数不一样);这个通用的系统可能给很多学校使用,每个学校根据自己的需求选择模块。
对于上面这个需求分析,1、由于这些模块都具有借书的功能,首先想到的是建立一个接口,接口中包含一个借书的函数,所有模块都要实现这个接口。
2、分别实现这些插件模块,编译成程序集DLL文件。
3、由于这是一个通用的系统,模块的选择应该由用户决定,因此我们不能预先把所有的模块功能都编译到系统中去(晚期绑定派上用场)。
4、用户选择一个模块(DLL文件),就相当于要加载一个程序集DLL(动态加载的概念),此时的DLL与用C/C++编写的DLL不一样,它是由微软中间语言IL组成的,里面记录了
DLL所有信息的元数据。
5、需要调用具体某个DLL模块中的具体借书函数,这个时候就需要从动态加载的DLL中获取到相应的类,实例化类,调用类的成员函数,这个就需要反射来干了。
6、有的时候在大型项目中,每个模块可能有不同的子部门来做,因此每个模块应该包好有这些部门的基本信息,这个时候在编写模块的功能时候,就可利用C#中的特性编程了,利用特性可以
给模块附加上额外的信息,这些信息会被编译到程序集中,同理我们也可以反射出这些信息来。
下面是一个简单代码的例子:利用了这些特性
插件接口的定义:
View Code
首先看一下简单项目的需求:程序员开发了很多模块,每个模块对应相应的功能,不同的用户可能需要使用的模块不一样,模块以插件的形式与系统集成,也就是提供给用户一个自定义模块的功能。
更加形象的比如:一个通用的图书馆里系统中有普通老师模块、有院长模块、有校长模块、有学生模块,这些模块都具有借书的功能(每个模块借书本数不一样);这个通用的系统可能给很多学校使用,每个学校根据自己的需求选择模块。
对于上面这个需求分析,1、由于这些模块都具有借书的功能,首先想到的是建立一个接口,接口中包含一个借书的函数,所有模块都要实现这个接口。
2、分别实现这些插件模块,编译成程序集DLL文件。
3、由于这是一个通用的系统,模块的选择应该由用户决定,因此我们不能预先把所有的模块功能都编译到系统中去(晚期绑定派上用场)。
4、用户选择一个模块(DLL文件),就相当于要加载一个程序集DLL(动态加载的概念),此时的DLL与用C/C++编写的DLL不一样,它是由微软中间语言IL组成的,里面记录了
DLL所有信息的元数据。
5、需要调用具体某个DLL模块中的具体借书函数,这个时候就需要从动态加载的DLL中获取到相应的类,实例化类,调用类的成员函数,这个就需要反射来干了。
6、有的时候在大型项目中,每个模块可能有不同的子部门来做,因此每个模块应该包好有这些部门的基本信息,这个时候在编写模块的功能时候,就可利用C#中的特性编程了,利用特性可以
给模块附加上额外的信息,这些信息会被编译到程序集中,同理我们也可以反射出这些信息来。
下面是一个简单代码的例子:利用了这些特性
插件接口的定义:
View Code
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Reflection; using CommonTypes; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void openToolStripMenuItem_Click(object sender, EventArgs e) { //选择一个插件加载 OpenFileDialog OFD = new OpenFileDialog(); if (OFD.ShowDialog() == DialogResult.OK) { if (!LoadModule(OFD.FileName)) MessageBox.Show("没有成功加载第三方的插件!"); } } private bool LoadModule(string path) { bool FindModule = false; Assembly asm = null; try { //加载指定路径下的程序集 asm = Assembly.LoadFrom(path); } catch (Exception ex) { MessageBox.Show(ex.Message); return FindModule; } //得到程序集中所有的IAppDll接口兼容的累 var ClassTypes = from t in asm.GetTypes() where t.IsClass && (t.GetInterface("IAppDll") != null) select t; //创建对象,并调用类中的方法 foreach (Type t in ClassTypes) { FindModule = true; //使用晚期绑定建立类型,强制转换为接口类型 IAppDll someApp =(IAppDll)asm.CreateInstance(t.FullName, true); someApp.DoThing(); listBox1.Items.Add(t.FullName); //显示插件的相关信息 DisplayCarinfo(t); } return FindModule; } //显示插件的信息 private void DisplayCarinfo(Type t) { var info = from carAtr in t.GetCustomAttributes(false) where (carAtr.GetType() == typeof(CarInfoAttribute)) select carAtr; //显示特性的属性 foreach (CarInfoAttribute cia in info) { MessageBox.Show(cia.name); } } } }
相关文章推荐
- C#2008与.NET 3.5 高级程序设计读书笔记(16)-- 类型反射、晚期绑定和基于特性的编程
- [C#]C#学习笔记-类型反射,晚期绑定,进程,对象上下文
- 分析 C# 2.0 新特性 -- 空类型(Nullable Types)
- 使用Java5特性来简化反射编程
- C#中使用反射显示程序集的所有类型和属性
- 使用Java5特性来简化反射编程
- c#使用反射调用类型成员示例
- C#中使用反射的性能分析-zz
- c# 特性/属性(Attribute) 以及使用反射查看自定义特性
- [导入]VS 2005中使用C#的新特性:可空类型
- C# 3.0新特性初步研究 Part1:使用隐含类型的本地变量
- 使用C#反射中的MakeGenericType函数,来为泛型方法和泛型类指定(泛型的)类型
- [导入]VS 2005中使用C#的新特性:可空类型
- C#反射,特性结合使用
- C#发现之旅第十一讲 使用反射和特性构造自己的ORM框架
- 【点滴积累】在C#中使用反射动态调用类型成员
- C# 使用‘反射(Assembly)’查找具有指定‘特性(Attributes) ’的类
- [导入]VS 2005中使用C#的新特性:可空类型
- C# 3.0新特性初步研究 Part1:使用隐含类型的本地变量_C#教程
- 如何:使用 Split 方法分析字符串(C# 编程指南)