C#反射的Assembly的简单应用
2011-11-30 20:46
357 查看
反射(Reflection)是.NET中的重要机制,通过反射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。
Assembly就是反应反射的一种应用,它定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。简单地说就是,使用Assembly在程序中你不用事先写比如下面的东西了:
你只要知道PersonClass这个类的程序集,命名空间和类名直接使用反射就可以使用。你只需要这样写:
下面用一个小例子来看看Assembly应用的方便性。
需求:有几种文件格式,后缀分别是.One,.Two,.Three,... 有很多种,后续还可能增加。这些文件的格式都不一样,也就是说读取方式就不一样。那么根据传入的文件后缀和路径读出文件的内容。
实现:
这种需求的特点是,根据选择做不同的处理,但是都是出的一种结果,那么可以使用简单工厂模式来完成。
读取文件有一个父类FileSuper,内部如下:
分别有MyFileOne,MyFileTwo,MyFileThree等,继承FileSuper,如下:
一个工厂类根据后缀名决定实例化哪个类:
客户端调用,显示结果:
这样解决了这个需求,前面在读书笔记6:工厂方法模式 中提到了这种方式的缺点,就是不符合开放封闭原则,那么如何改进了,除了工厂方法模式,我们可以使用Assembly。使用它之前,要先写一个类和一个配置文件。
先看配置文件:MyFile.xml
是后缀名和类名的对应。
另一个读取配置文件的类ExtendNameDataTable。
做好这两个准备后,只需修改OperationFile工厂类,其余都不用修改。使用Assembly来根据配置文件,自动按照传入的后缀名加载类,并且实例化,修改后的OperationFile如下:
客户端调用不变输出结果:
我们看到,这样一来,如果有了新的文件结构,只需要再写一个MyFileFour类继承自FileSuper;然后再在MyFile.xml中增加相应的对应关系就可以了,避免了要修改OperationFile的case分支,符合开放封闭原则。
当然Assembly这么好使用,也不是所有情况下都能用的,当在循环中碰到了这种情况,那么还是使用简单工厂模式或者工厂方法模式吧,因为再循环中使用Assembly实例化会导致性能下降。
Assembly就是反应反射的一种应用,它定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。简单地说就是,使用Assembly在程序中你不用事先写比如下面的东西了:
PersonClass person = new PersonClass(); person.Method();
你只要知道PersonClass这个类的程序集,命名空间和类名直接使用反射就可以使用。你只需要这样写:
PersonClass person; person = person = (PersonClass)(Assembly.Load("程序集").CreateInstance("命名空间.类名", false, BindingFlags.Default, null, args, null, null)); person.Method();
下面用一个小例子来看看Assembly应用的方便性。
需求:有几种文件格式,后缀分别是.One,.Two,.Three,... 有很多种,后续还可能增加。这些文件的格式都不一样,也就是说读取方式就不一样。那么根据传入的文件后缀和路径读出文件的内容。
实现:
这种需求的特点是,根据选择做不同的处理,但是都是出的一种结果,那么可以使用简单工厂模式来完成。
读取文件有一个父类FileSuper,内部如下:
using System; using System.Collections.Generic; using System.Text; namespace reflect { public abstract class FileSuper//获取不同后缀名文件的内容 { public abstract string GetFileContext(string fileFullPath); } }
分别有MyFileOne,MyFileTwo,MyFileThree等,继承FileSuper,如下:
using System; using System.Collections.Generic; using System.Text; namespace reflect { public class MyFileOne : FileSuper { public override string GetFileContext(string fileFullPath) { return "One类型文件的内容"; } } }
using System; using System.Collections.Generic; using System.Text; namespace reflect { public class MyFileTwo : FileSuper { public override string GetFileContext(string fileFullPath) { return "Two类型文件的内容"; } } }
using System; using System.Collections.Generic; using System.Text; namespace reflect { public class MyFileThree : FileSuper { public override string GetFileContext(string fileFullPath) { return "Three类型文件的内容"; } } }
一个工厂类根据后缀名决定实例化哪个类:
using System; using System.Collections.Generic; using System.Text; namespace reflect { public class OperationFile { static FileSuper fileSuper = null; public static string GetStringByFile(string fileFullPath, string extendName) { switch (extendName) { case "One": fileSuper = new MyFileOne(); break; case "Two": fileSuper = new MyFileTwo(); break; case "Three": fileSuper = new MyFileThree(); break; } if (fileSuper != null) { return fileSuper.GetFileContext(fileFullPath); } return "没有指定的类型"; } } }
客户端调用,显示结果:
using System; using System.Collections.Generic; using System.Text; namespace reflect { public class Program { static void Main(string[] args) { string fileContext = OperationFile.GetStringByFile("路径", "One"); Console.WriteLine(fileContext); Console.ReadLine(); } } }
这样解决了这个需求,前面在读书笔记6:工厂方法模式 中提到了这种方式的缺点,就是不符合开放封闭原则,那么如何改进了,除了工厂方法模式,我们可以使用Assembly。使用它之前,要先写一个类和一个配置文件。
先看配置文件:MyFile.xml
<?xml version="1.0" encoding="utf-8" ?> <FileExtendName> <extend> <name>One</name> <class>MyFileOne</class> </extend> <extend> <name>Two</name> <class>MyFileTwo</class> </extend> <extend> <name>Three</name> <class>MyFileThree</class> </extend> </FileExtendName>
是后缀名和类名的对应。
另一个读取配置文件的类ExtendNameDataTable。
using System; using System.Collections.Generic; using System.Text; using System.Data; namespace reflect { public class ExtendNameDataTable { private static DataSet extendDataSet; public static DataSet ExtendDataSet { get { if (extendDataSet == null) { extendDataSet = new DataSet(); extendDataSet.ReadXml(@"F:\MyFile.xml"); } return extendDataSet; } } } }
做好这两个准备后,只需修改OperationFile工厂类,其余都不用修改。使用Assembly来根据配置文件,自动按照传入的后缀名加载类,并且实例化,修改后的OperationFile如下:
using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Reflection; namespace reflect { public class OperationFile { public static string GetStringByFile(string fileFullPath, string extendName) { DataRow dr = ((DataRow[])ExtendNameDataTable.ExtendDataSet.Tables[0].Select("name='" + extendName + "'"))[0]; object[] args = null; FileSuper fileSuper; fileSuper = (FileSuper)(Assembly.Load("reflect").CreateInstance( "reflect." + dr["class"].ToString(), false, BindingFlags.Default, null, args, null, null)); return fileSuper.GetFileContext(fileFullPath); } } }
客户端调用不变输出结果:
我们看到,这样一来,如果有了新的文件结构,只需要再写一个MyFileFour类继承自FileSuper;然后再在MyFile.xml中增加相应的对应关系就可以了,避免了要修改OperationFile的case分支,符合开放封闭原则。
当然Assembly这么好使用,也不是所有情况下都能用的,当在循环中碰到了这种情况,那么还是使用简单工厂模式或者工厂方法模式吧,因为再循环中使用Assembly实例化会导致性能下降。
相关文章推荐
- C#反射的Assembly的简单应用
- C#反射 Assembly的简单应用
- C#反射的Assembly的简单应用
- C#反射的Assembly的简单应用
- C#反射的Assembly的简单应用
- C#反射简单应用
- 【原创】 ASP.NET C#反射简单实例应用
- 简单讲解C#反射之Assembly
- C#反射的应用【转】
- [转]使用C#开发一个简单的P2P应用
- c#devexpres TreeList 最简单显示动态值的应用
- C# 反射技术应用
- C#基础--Attribute(标签) 和 reflect(反射) 应用
- asp.net(c#)中使用反射动态加载dll简单示例
- C#反射Assembly 详细说明
- C#反射之一(Assembly.Load及Assembly.Load.CreateInstance方法介绍)
- C#调用Dll文件中方法的简单应用
- C# TimSpan 简单应用
- .m文件编译成com/.Net Assembly以及C#反射
- c# 反射简单用法例子