1. 概述

  一个.net程序不仅包含代码和数据,还包含 元数据

  本章介绍如何应用attributes以及如何使用反射来获取它,还有如何使用CodeDomexpression trees来实现在运行时生成代码。

2. 主要内容

  2.1 创建和使用attributes

    ① attributes用来向程序添加元数据。可以应用到所有类型:程序集、类、方法、参数、属性。

  1. [Conditional("CONDITION1"), Conditional("CONDITION2")]
  2. static void MyMethod() { }

    ② AssemblyInfo.cs中保存的是应用到当前程序集的所有attributes。

    ③ 可以使用attributes的IsDefined和GetCustomAttribute方法读取attributes

  1. if (Attribute.IsDefined(typeof(Person), typeof(SerializableAttribute)))
  2. { }
  3.  
  4. ConditionalAttribute conditionalAttribute =
  5. (ConditionalAttribute)Attribute.GetCustomAttribute(
  6. typeof(ConditionalClass),
  7. typeof(ConditionalAttribute));
  8.  
  9. string condition = conditionalAttribute.ConditionString; //CONDITION1

    ④ 可以自定义attributes

  1. [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
  2. AllowMultiple=true)]
  3. class CompleteCustomAttribute : Attribute
  4. {
  5. public CompleteCustomAttribute(string description)
  6. {
  7. Description = description;
  8. }
  9. public string Description {get; set; }
  10. }

  2.2 使用反射

    反射 使得一个应用程序可以收集自身的信息并使用。反射的运行速度比其他静态代码慢。

  1. public interface IPlugin
  2. {
  3. string Name { get; }
  4. string Description {get; }
  5. bool Load(MyApplication application);
  6. }
  7.  
  8. Assembly pluginAssembly = Assembly.Load("assemblyName");
  9.  
  10. var plugins = from type in pluginAssembly.GetTypes()
  11. where typeof(IPlugin).IsAssignableFrom(type) && !type.IsInterface
  12. select type;
  13.  
  14. foreach(Type pluginType in plugins)
  15. IPlugin plugin = Activitor.CreateInstance(pluginType) as IPlugin;

    使用反射还可以获取属性的值和执行指定的方法。

  1. int i = ;
  2. MethodInfo compareToMethod = i.GetType().GetMethod("CompareTo"
  3. , new Type[] { typeof(int) };
  4. int result = (int)compareToMethod.Invoke(i, new object[] { });

  2.3 使用CodeDom和Lambda表达式生成代码

    ① 使用CodeDom

  1. CodeCompileUnit compileUnit = new CodeCompileUnit();
  2. CodeNamespace myNamespace = new CodeNamespace("MyNamespace");
  3. myNamespace.Imports.Add(new CodeNamespaceImport("System"));
  4. CodeTypeDeclaration myClass = new CodeTypeDeclaration("MyClass");
  5. CodeEntryPointMethod start = new CodeEntryPointMethod();
  6. CodeMethodInvokeExpression cs1 = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodePrimitiveExpression("Hello World!"));
  7.  
  8. compileUnit.Namespaces.Add(myNamespace);
  9. myNamespace.Types.Add(myClass);
  10. myClass.Members.Add(start);
  11. start.Statements.Add(cs1);

    编译单元定义完成后,使用CSharpCodeProvider来执行生成。

  1. CSharpCodeProvider provider = new CSharpCodeProvider();
  2.  
  3. using(StreamWriter sw = new StreamWriter("HelloWorld.cs", false))
  4. {
  5. IndentedTextWriter tw = new IndentedTypeWriter(sw, " ");
  6. provider.GenerateCodeFromCompileUnit(compileUnit, tw, new CodeGeneratorOptions());
  7. tw.Close();
  8. }

    ② 使用 expression trees 实现上述功能

  1. BlockExpression blockExpr = Expression.Block(
  2. Expression.Call(
  3. null,
  4. typeof(Console).GetMethod("Write", new Type[] { typeof(String)}), Expression.Constant("Hello ")
  5. ),
  6. Expression.Call(
  7. null,
  8. typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String)}), Expression.Constant("World!")
  9. ),
  10. );
  11.  
  12. Expression.Lambda<Action>(blockExpr).Compile();

3. 总结

  ① 一个C#程序集包括代码和元数据。

  ② Attributes是元数据的一种,可以被应用到代码中,可以在运行时被查询到。

  ③ 反射是一个在C#程序中检查元数据的过程。

  ④ 利用反射,可以 创建类型、调用方法、读取属性 等等。

  ⑤ CodeDom用于在运行时创建一个编译单元。可以被编译或转化成源码文件。

  ⑥ 表达式树 描述一块代码,可以被翻译成其他语言(比如sql),也可以被编译和执行。

第十章 管理类型(In .net4.5) 之 使用反射的更多相关文章

  1. 第十一章 管理类型(In .net4.5) 之 管理对象的生命周期

    1. 概述 本章内容包括 管理非托管资源.使用IDisposable接口 以及 管理析构器和垃圾回收. 2. 主要内容 2.1 理解垃圾回收机制 ① 代码执行的时候,内存中有两个地方存放数据项:堆 和 ...

  2. 第十二章 管理类型(In .net4.5) 之 操作字符串

    1. 概述 本章包括 字符串基本操作 以及 查找.遍历.格式化字符串. 2. 主要内容 2.1 在.net平台中使用字符串 C#中,string是用来保存文本信息的.是一个被当做值类型使用的引用类型. ...

  3. 第八章 管理类型(In .net4.5) 之 加强封装

    1. 概述 本章内容包括 访问控制符.属性 和 显式接口实现. 2. 主要内容 2.1 访问控制符 封装的核心是隐藏信息.访问控制符用来实现类型成员的访问控制. C#的访问控制符有:public, i ...

  4. 第七章 管理类型(In .net4.5) 之 使用类型

    1. 概述 本章介绍 值类型的装箱拆箱.类型转换 以及 C#4.0新推出的 dynamic 关键字. 2. 主要内容 2.1 装箱和拆箱 2.2 类型转换 有四种方式可以实现类型转换: ① 隐式转换: ...

  5. 第六章 管理类型(In .net4.5) 之 创建类型

    1. 概述 本章内容包括 C#5中如何更好的创建类型以及如何扩展现有类型. 2. 主要内容 2.1 如何选择类型 C#类型系统包括三种类型:值类型.引用类型.指针类型.(指针类型用于非托管代码,很少使 ...

  6. 第九章 管理类型(In .net4.5) 之 继承机制

    1. 概述 本章包括 设计和实现接口.创建和使用基类 以及 使用.net类库提供的标准接口. 2. 主要内容 2.1 设计和实现接口 一个接口包含公共的方法.属性.事件.索引器.类和结构都可以实现接口 ...

  7. EJB3 EntityBean中EntityManager的管理类型

    EJB中EntityManager的管理方式有两种:Container-managed EntityManager和Application-managed EntityManager 即容器管理的En ...

  8. Spring支持的事务管理类型?

    Spring支持两种类型的事务管理: 编程式事务管理 :这意味你通过编程的方式管理事务,给你带来极大的灵活性,但是难维护. 声明式事务管理: 这意味着你可以将业务代码和事务管理分离,你只需用注解和XM ...

  9. 列举 spring 支持的事务管理类型?

    Spring 支持两种类型的事务管理: 1. 程序化事务管理:在此过程中,在编程的帮助下管理事务.它为您提供极大 的灵活性,但维护起来非常困难. 2. 声明式事务管理:在此,事务管理与业务代码分离.仅 ...

随机推荐

  1. 分享一个基于EF5.0封装的BaseDAL

    public class BaseDAL<T> where T : class,new() { protected DbContext dbContext = DbContextFacto ...

  2. FileZilla - Windows XP经典软件系列

    官网: https://filezilla-project.org/ 下载: http://sourceforge.net/projects/filezilla/ 版本:V3.9.0.1 (支持XP最 ...

  3. ofstream的问题

    ofstream在多字节编码的项目中, 写入中文目录写不了, 英文目录可以 换成c库的fopen, fwrite可以

  4. Orchard官方文档翻译(七) 导航与菜单

    原文地址:http://docs.orchardproject.net/Documentation/Navigation-and-menus 想要查看文档目录请用力点击这里 最近想要学习了解orcha ...

  5. C# 枚举显示中文

    转自:http://www.cnblogs.com/yank/archive/2011/09/08/EnumDisplayInChinese.html   using System; using Sy ...

  6. 合并同一目录下多个EXCEL的多个sheet

    合并同一目录下多个EXCEL的多个sheet到一个excel的一个sheet 1.把多个excel表都放在同一个文件夹里面,并在这个文件夹里面新建一个excel2.打开新建的excel表,并右键单击s ...

  7. excel中单元格计算

    首先,得明确excel中相对引用和绝对引用的概念,这里$符号起着关键作用,当在一个行或列的指示符前面加$则表示绝对引用,否则相对引用,具体: 1.相对引用,复制公式时地址跟着发生变化,如C1单元格有公 ...

  8. (转)Java基础——嵌套类、内部类、匿名类

    本文内容分转自博客:http://www.cnblogs.com/mengdd/archive/2013/02/08/2909307.html 将相关的类组织在一起,从而降低了命名空间的混乱. 一个内 ...

  9. TCP/IP详解学习笔记(15)-- TCP的流量控制和拥塞控制

    TCP的流量控制 1.概述      所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受.利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制.TCP的窗口单位是字节,不是报 ...

  10. 如何利用百度地图JSAPI画带箭头的线?

    百度地图JSAPI提供两种绘制多折线的方式,一种是已知多折线经纬度坐标串通过AddOverlay接口进行添加:另一种是通过在地图上鼠标单击进行绘制(鼠标绘制工具条库).目前这两种方式只能绘制多折线,并 ...