反射(Reflection)是.NET中的重要机制,通过反射,可以在运行时获得.NET中每一个类型(包括类、结构、委托、接口和枚举等)的成员,包括方法、属性、事件,以及构造函数等。还可以获得每个成员的名称、限定符和参数等。有了反射,即可对每一个类型了如指掌。如果获得了构造函数的信息,即可直接创建对象,即使这个对象的类型在编译时还不知道。

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实例化会导致性能下降。

转载于:https://blog.51cto.com/yangyoushan/1276875

C#反射的Assembly的简单应用相关推荐

  1. golang利用反射写入excel的简单工具类

    golang利用反射写入excel的简单工具类 工具类源码 使用方法 工具类源码 package excelimport ("errors""github.com/tea ...

  2. C#反射之Assembly.Load,Assembly.LoadFile 与 Assembly.LoadFrom方法介绍

    一些关于C#反射的知识,估计也就最多达到使用API的程度,至于要深入了解,以现在的水平估计很难做到,所以下面此篇文章,以作为一个阶段的总结. 对于反射的总结,我想从以下几个方面展开,首先是反射程序集, ...

  3. C# 反射类Assembly用法举例

    概述 程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息,包括类.函数.变量等来实例化它们,执行它们,操作它们,实际上就是获取程序在内存中的映像,然后基于这个映像进行各种操作. Ass ...

  4. Java反射Method和Field简单实例

    目录 定义 使用方法 1.Field 2.Method 3.简单实例 定义 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方 ...

  5. Maven自定义打包插件Assembly Plugin简单使用

    使用Assembly Plugin实现自定义打包 1.修改pom.xml <!-- 编译时自动打包,规则见distribution.xml文件--> <build><pl ...

  6. 【java反射】简单说说静态代理和动态代理

    在上篇博客中,我们说了反射的原理和简单应用,这次我们说说反射更深一层的应用,即动态代理. 代理模式 定义 代理模式是为其他对象提供一种代理以控制对这个对象的访问.代理模式分为静态代理和动态代理. 原理 ...

  7. 设计模式之反射与配置文件

    为了满足"开闭原则",大部分设计模式都引入了抽象层,如工厂方法模式.抽象工厂模式.适配器模式.桥接模式.命令模式.策略模式等等.客户端代码针对抽象层编程,而在程序运行的时候再指定其 ...

  8. 使用ImpromptuInterface反射方便的创建自定义DfaGraphWriter

    在本文中,我为创建的自定义的DfaGraphWriter实现奠定了基础.DfaGraphWriter是公开的,因此您可以如上一篇文章<将终结点图添加到你的ASP.NET Core应用程序中> ...

  9. XsdGen:通过自定义Attribute与反射自动生成XSD

    前言 系统之间的数据交互往往需要事先定义一些契约,在WCF中我们需要先编写XSD文件,然后通过自动代码生成工具自动生成C#对象.对于刚刚接触契约的人来说,掌握XMLSpy之类的软件之后确实比手写XML ...

最新文章

  1. Zepto.js简介
  2. android o 小米note 3,小米 Note 3 MIUI 10 安卓 8.0 内测开启
  3. C# xml文件的创建,修改和添加节点 。
  4. 逻辑漏洞——权限控制问题
  5. 使用.Net Core实现FNV分布式hash一致性算法
  6. app自动化测试之Appium 源码分析
  7. POJ 2709 Painter 【贪心算法】
  8. 如何使用JSTL及JSTL标签库
  9. python日期模块datetime常用操作总结(字符串与datetime对象互转、日期差值计算、时间戳获取、时间数组生成等)
  10. android MySQL servlet_使用MySQL和Servlet编写Android接口样例
  11. 百度音乐怎么转换格式?MP3格式转换为wav的方法分享
  12. 分享一个WIN10可用的桌面图标栅栏管理插件Fences的破解版
  13. matlab gui制作,MATLAB GUI制作教程
  14. 牛腩--SQLHelper
  15. 【工具使用系列】PostScript工具 GhostScript,GSview,Epstool,RedMon
  16. 34岁IBM工程师电脑被抢身亡:以命相争背后,是无处安放的生活
  17. oracle 索引快速全扫描,使用目录快速全扫描(Index FFS)避免全表扫描的若干场景
  18. 消费金融进入“第二赛段”,突围关键是什么?
  19. vue 中使用 cesium
  20. 另类的 ETL 工具 sed 进阶

热门文章

  1. 修改鼠标手形 闪烁 在填写文字内容后也一直在闪烁
  2. php 网络图片 execl,phpexcel图片获取
  3. 低解密指数攻击_CTF中RSA的一些攻击思路
  4. java辅助百度贴吧_【图片】【共同上进】新手java代码辅助代写贴,新手福音! 申精!_java吧_百度贴吧...
  5. layui php ajax分页,layui+thinkphp5.1实现分页(非动态表格)
  6. axios请求拦截器错误_React中使用高阶组件和axios的拦截器,统一处理请求失败提示...
  7. 如何隐藏地址栏中的真实地址_代理IP如何隐藏真实IP
  8. python检测excel是否打开_Python判断远程服务器上Excel文件是否被人打开的方法_学领未来...
  9. 手机wps列怎样转成行_为什么有人不用免费的WPS,偏要花钱用Office?看完这些就知道了...
  10. 安卓怎么把一个按钮设计成梯形_常闭触点输入信号处理的电路图及PLC梯形图