1 / 31

在本章,你将学到: 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据

在本章,你将学到: 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据. 目标. 重点 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据 难点 创建自定义属性 使用反射抽取元数据. 重点与难点. 教学计划. 对象是由它们的属性描述的。 属性是用于传递关于程序元素行为,例如类、枚举器和汇编的信息到运行时的声明标签。 声明标签是由放置在元素例如类或方法之前的方括号 ([ ]) 描述的。 属性被用来添加元数据例如编译器指令和其他信息,例如注释、描述、方法和程序的类。 .NET 框架具有许多预定义的属性。. 介绍属性.

irina
Download Presentation

在本章,你将学到: 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 在本章,你将学到: 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据 目标

  2. 重点 应用属性 使用预定义属性 创建自定义属性 使用反射抽取元数据 难点 创建自定义属性 使用反射抽取元数据 重点与难点

  3. 教学计划

  4. 对象是由它们的属性描述的。 属性是用于传递关于程序元素行为,例如类、枚举器和汇编的信息到运行时的声明标签。 声明标签是由放置在元素例如类或方法之前的方括号([ ])描述的。 属性被用来添加元数据例如编译器指令和其他信息,例如注释、描述、方法和程序的类。 .NET框架具有许多预定义的属性。 介绍属性

  5. 属性被应用到不同的代码元素。 属性被应用到不同的代码元素。这些元素包括汇编、模块、类、结构、枚举、构造函数、方法、特性、域、事件、接口、参数、返回值和代理。关于属性的信息被存储在与它们相关的元素的元数据中。 下面的语法使你能够指定属性: [attribute(positional_parameters,name_parameter = value, ...)] element .NET框架支持两种类型的属性以用于C#程序: 预定义 自定义 应用属性

  6. 一些常用的.NET框架提供的预定义属性有: Conditional(条件)属性 引起方法调用的条件编译,依赖与特定的值例如Debug或Trace。这个属性决定当一个方法被调用的时候,将发生的动作(在代码执行过程中运不运行调用的函数的代码)示例如下: using System ; class HappyAppy { [conditional ( "DEBUG" )] public static void DebugOnlyMethod ( ) { Console.WriteLine ( "DEBUG is active!!" ) ; } public static void Main ( ){ DebugOnlyMethod ( ) ; } } #define DEBUG //只有在前面定义了,后面的DebugOnlyMethod 函数才会被调用 Class usefunction{ public static void Main ( ){ HappyAppy 0bj = new HappyAppy(); Obj.DebugOnlyMethod ( ) ; //因前面定义了,所以才会调用此函数 } } #if (DEBUG) Console.WriteLine(“DEBUG”); //在调试状态下运行此行代码 #else Console.WriteLine(“Release”); //在运行状态下运行些行代码 #endif 使用预定义属性

  7. 一些常用的.NET框架提供的预定义属性有: WebMethod 决定在网页服务中暴露的方法,示例如下: <@% WebService class="MathServiceJit" language="C#"%> using System.Web.Services;public class MathService{   [WebMethod]   public double Add(double x, double y) {      return x + y;   }   [WebMethod]   public double Subtract(double x, double y) {      return x - y;   }   public double Multiply(double x, double y) {      return x * y;   }   public double Divide(double x, double y) {      return x / y;   }} 使用预定义属性

  8. 运行结果如下 使用预定义属性

  9. DLLImport属性 在程序中调用在.net环境外开发的未管理的代码,如编译为DLL文件的标准C程序,如使用 kernel32.dll文件中的Beep(int f,int d)函数: using System; class geneBeeps{ [ DLLImport (kernel32.dll)] public static extern bool Beep(int f, int d); static void Main(){ Beep(1000,1111); } } 使用预定义属性

  10. Obsolete(过时的)属性 using System; public Class Myclass{ [Obsolete(“提示A不能被使用,要使用B”,true)]//true表将产生一个错误,为false产生一个警告 static void A(){ } Staitc void B(){ } Public static void Main(){ A();//将产生一个错误,提示“A不能被使用,要使用B” } } 使用预定义属性

  11. .NET框架允许创建自定义属性,它可以被用于存储信息和在运行时被获取。.NET框架允许创建自定义属性,它可以被用于存储信息和在运行时被获取。 这个信息可以与任何目标元素相关,依赖与设计和程序的需要。 为了创建自定义属性,你需要: 定义自定义属性 命名自定义属性 构造自定义属性 为目标元素应用自定义属性 创建自定义属性

  12. 定义自定义属性: 一个新自定义属性类来源于System.Attribute系统类。 你需要使用预定义的属性应用属性目标到新的自定义属性类,AttributeUsage,如下面的代码所示: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] 创建自定义属性(续)

  13. AttributeUsage属性接受两个参数: 一个参数是表示目标元素的一系列标志,表示下面的属性可以被应用在哪些数据元素中,如method,class等。是一个对属性使用范围作限制的参数 其他参数是表示一个给定的元素是否被应用于多个这样属性的标志。 除了AllowMultiple特性,还有其他特性可以与属性一起使用。这些特性是: Inherited:为true是表示该类使用的属性能被子类继承,为false表不能被继承 ValidOn:这个特性有助于定义目标元素,在它上面自定义属性被应用。 创建自定义属性(续)

  14. 创建自定义属性(续) • 下表列出了AttributeTargets枚举器的各种成员名称。

  15. 命名自定义属性: 通常的约定是在属性名称后添加单词Attribute。 编译器通过允许你使用名称的简短版本来调用属性以支持添加。 创建自定义属性(续)

  16. 创建自定义属性(续) • 构造自定义属性: • 每个属性必须包含至少一个构造函数。 • 位置参数通过构造函数被以构造函数中声明的顺序传递,如下面的代码段所示: public BugFixingAttribute(int BugNo, string Developer, string DateFixed) { this.BugNo = BugNo; this.Developer = Developer; this.DateFixed = DateFixed; }

  17. 创建自定义属性(续) • 命名参数被实现为特性,如下面的代码段所示: public string Remarks { get { return Remarks; } set { Remarks = value; } }

  18. 为位置参数创建只读属性是很常见的: public int BugNo { get { return BugNo; } } 创建自定义属性(续)

  19. 应用自定义属性: 属性可以通过将它立刻放置在它的目标之前被应用。 为了测试上述例子的BugFixAttribute属性,你可以创建一个简单的名为Calculator类的程序,给出四个函数。 你需要指定BugFixAttribute为目标元素类以记录它的代码维护历史,如下面的代码所示: [BugFixingAttribute(125,"Sara Levo","08/15/06", Remarks="Return object not specified")] [BugFixingAttribute(159,"Sara Levo","08/17/06", Remarks="Data Type Mismatch")] public class Calculator 创建自定义属性(续)

  20. 创建一个属性,在一个类中应用,并把相关应用的属性元数据信息显示出来创建一个属性,在一个类中应用,并把相关应用的属性元数据信息显示出来 代码如下: using System; using System.Reflection; namespace Lesson13_Ex { // create BugFixingAttribute custom attribute to be assigned to class members [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] [DescriptionAttribute("This class contains defination of Bug Fixing attribute", 2.0)] public class BugFixingAttribute : System.Attribute { private int bugNo; private string developer; private string dateFixed; public string remarks; // attribute constructor for positional parameters public BugFixingAttribute(int BugNo, string Developer, string DateFixed) { this.bugNo = BugNo; this.developer = Developer; this.dateFixed = DateFixed; } public int BugNo { get { return bugNo; } } public string DateFixed { get { return dateFixed; } } public string Developer { get { return developer; } } public string Remarks { get { return remarks; } set { remarks = value; } } } // create DescriptionAttribute custom attribute to be assigned to class members [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] [DescriptionAttribute("This class contains defination of Description attribute", 1.0)] public class DescriptionAttribute : System.Attribute { // attribute constructor for positional parameters public DescriptionAttribute(string Description, double Version) { this.description = Description; this.version = Version; } protected String description; public String Description { get { return this.description; } } protected Double version; public Double Version { get { return this.version; } set { this.version = value; } } } [BugFixingAttribute(125, "Sara Levo", "08/15/06", Remarks = "Return object not specified")] [BugFixingAttribute(159, "Sara Levo", "08/17/06", Remarks = "Data Type Mismatch")] [DescriptionAttribute("This class contains two methods", 1.0)] public class Calculator { public double Add(Double num1, Double num2) { return num1 + num2; } public double Subtract(Double num1, Double num2) { return num1 - num2; } [BugFixingAttribute(155, "Sara Levo", "08/16/06")] public double Multiply(Double num1, Double num2) { return num1 * num2; } [BugFixingAttribute(156, "Sara Levo", "08/16/06")] public double Divide(Double num1, Double num2) { return num1 / num2; } } [DescriptionAttribute("This class contains the Main method", 2.0)] public class EntryPoint { public static void Main() { Calculator MyObj = new Calculator(); Console.WriteLine("The sum of specified two nos are: {0}", MyObj.Add(15, 20.5)); Type type = typeof(Calculator); // iterating through the attributes of the Calculator class foreach (Object attributes in type.GetCustomAttributes(typeof(BugFixingAttribute), false)) { BugFixingAttribute MyBFAObj = (BugFixingAttribute)attributes; if (null != MyBFAObj) { Console.WriteLine("\nBug #: {0}", MyBFAObj.BugNo); Console.WriteLine("Developer: {0}", MyBFAObj.Developer); Console.WriteLine("Date Fixed: {0}", MyBFAObj.DateFixed); Console.WriteLine("Remarks: {0}", MyBFAObj.Remarks); } } // iterating through the attributes of all the methods of a Calculator class foreach (MethodInfo method in type.GetMethods()) { foreach (Attribute attributes in method.GetCustomAttributes(true)) { BugFixingAttribute MyBFAObjM = (BugFixingAttribute)attributes; if (null != MyBFAObjM) { Console.WriteLine("\nBug #: {0} for Method: {1}", MyBFAObjM.BugNo, method.Name); Console.WriteLine("Developer: {0}", MyBFAObjM.Developer); Console.WriteLine("Date Fixed: {0}", MyBFAObjM.DateFixed); Console.WriteLine("Remarks: {0}", MyBFAObjM.Remarks); } } } foreach (Object attributes in type.GetCustomAttributes(typeof(DescriptionAttribute), false)) { DescriptionAttribute MyDAObj = (DescriptionAttribute)attributes; if (null != MyDAObj) { Console.WriteLine("\nClass : Calculator - Description :{0} - Version {1}", MyDAObj.Description, MyDAObj.Version); } } type = null; type = typeof(EntryPoint); foreach (Object attributes in type.GetCustomAttributes(false)) { DescriptionAttribute MyDAObj = (DescriptionAttribute)attributes; Console.WriteLine("\nClass : EntryPoint - Description :{0} - Version {1}", MyDAObj.Description, MyDAObj.Version); } Console.ReadLine(); } } } 练习

  21. 反射在运行时被使用在获得类型信息的过程中。反射在运行时被使用在获得类型信息的过程中。 提供访问运行程序的元数据的类时在System.Reflection命名空间中。 System.Reflection命名空间包含允许程序员获取关于运行的程序的信息的类,以动态的添加类型、值和对象到那个程序。 使用反射抽取元数据

  22. 反射通常用于下面的任务: 浏览元数据 完成类型发现 方法和特性的后期绑定 反射发出 使用反射抽取元数据(续)

  23. 浏览元数据: 为了使用反射来浏览元数据,System.Reflection命名空间的MemberInfo对象需要被实例化。 这个对象有助于发现成员的属性并且提供对元数据的访问。 使用反射抽取元数据(续)

  24. 完成类型发现: 反射也有助于浏览和检查汇编的内容。 它有助于发现与模块相关的类型;方法、域、属性和与类型相关的事件以及方法的每个类型的签名;类型支持的接口和类型的基类。 类型发现信息也可以通过Visual Studio .NET IDE的对象浏览器窗口来浏览。 使用反射抽取元数据(续)

  25. 后期绑定: 在运行时绑定一个方法被称为后期绑定。 反射提供了选择一个你在运行时绑定的对象的灵活性,并且可以程序化的调用它。 使用反射抽取元数据(续)

  26. 反射发出: 反射发出允许在运行时创建新的类型,而且使用这些类型来完成某些任务。 反射发出允许在运行时创建新的类型,而且使用这些类型来完成某些任务。 使用带事件的反射

  27. 问题描述: John是一个软件开发公司的开发人员。程序经理想让John确保Calculator程序的商业逻辑的适当文档作为开发过程的一部分。尽管,公司维护一个独立的描述类的使用和它们的版本号的独立表格,当时程序经理想将表格添加到类中。 [提示:使用上面给出的Calculator类提供商业逻辑。] 演示:创建和查询自定义属性信息

  28. 解决方案: 为了为Calculator程序创建基于控制台的程序,John需要完成下面的任务: 创建基于控制台的程序。 创建和执行程序。 程序代码 using System; using System.Reflection; namespace Lesson13_Ex { // create BugFixingAttribute custom attribute to be assigned to class members [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] [DescriptionAttribute("This class contains defination of Bug Fixing attribute", 2.0)] public class BugFixingAttribute : System.Attribute { private int bugNo; private string developer; private string dateFixed; public string remarks; // attribute constructor for positional parameters public BugFixingAttribute(int BugNo, string Developer, string DateFixed) { this.bugNo = BugNo; this.developer = Developer; this.dateFixed = DateFixed; } public int BugNo { get { return bugNo; } } public string DateFixed { get { return dateFixed; } } public string Developer { get { return developer; } } public string Remarks { get { return remarks; } set { remarks = value; } } } // create DescriptionAttribute custom attribute to be assigned to class members [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] [DescriptionAttribute("This class contains defination of Description attribute", 1.0)] public class DescriptionAttribute : System.Attribute { // attribute constructor for positional parameters public DescriptionAttribute(string Description, double Version) { this.description = Description; this.version = Version; } protected String description; public String Description { get { return this.description; } } protected Double version; public Double Version { get { return this.version; } set { this.version = value; } } } [BugFixingAttribute(125, "Sara Levo", "08/15/06", Remarks = "Return object not specified")] [BugFixingAttribute(159, "Sara Levo", "08/17/06", Remarks = "Data Type Mismatch")] [DescriptionAttribute("This class contains two methods", 1.0)] public class Calculator { public double Add(Double num1, Double num2) { return num1 + num2; } public double Subtract(Double num1, Double num2) { return num1 - num2; } [BugFixingAttribute(155, "Sara Levo", "08/16/06")] public double Multiply(Double num1, Double num2) { return num1 * num2; } [BugFixingAttribute(156, "Sara Levo", "08/16/06")] public double Divide(Double num1, Double num2) { return num1 / num2; } } [DescriptionAttribute("This class contains the Main method", 2.0)] public class EntryPoint { public static void Main() { Calculator MyObj = new Calculator(); Console.WriteLine("The sum of specified two nos are: {0}", MyObj.Add(15, 20.5)); Type type = typeof(Calculator); // iterating through the attributes of the Calculator class foreach (Object attributes in type.GetCustomAttributes(typeof(BugFixingAttribute), false)) { BugFixingAttribute MyBFAObj = (BugFixingAttribute)attributes; if (null != MyBFAObj) { Console.WriteLine("\nBug #: {0}", MyBFAObj.BugNo); Console.WriteLine("Developer: {0}", MyBFAObj.Developer); Console.WriteLine("Date Fixed: {0}", MyBFAObj.DateFixed); Console.WriteLine("Remarks: {0}", MyBFAObj.Remarks); } } // iterating through the attributes of all the methods of a Calculator class foreach (MethodInfo method in type.GetMethods()) { foreach (Attribute attributes in method.GetCustomAttributes(true)) { BugFixingAttribute MyBFAObjM = (BugFixingAttribute)attributes; if (null != MyBFAObjM) { Console.WriteLine("\nBug #: {0} for Method: {1}", MyBFAObjM.BugNo, method.Name); Console.WriteLine("Developer: {0}", MyBFAObjM.Developer); Console.WriteLine("Date Fixed: {0}", MyBFAObjM.DateFixed); Console.WriteLine("Remarks: {0}", MyBFAObjM.Remarks); } } } foreach (Object attributes in type.GetCustomAttributes(typeof(DescriptionAttribute), false)) { DescriptionAttribute MyDAObj = (DescriptionAttribute)attributes; if (null != MyDAObj) { Console.WriteLine("\nClass : Calculator - Description :{0} - Version {1}", MyDAObj.Description, MyDAObj.Version); } } type = null; type = typeof(EntryPoint); foreach (Object attributes in type.GetCustomAttributes(false)) { DescriptionAttribute MyDAObj = (DescriptionAttribute)attributes; Console.WriteLine("\nClass : EntryPoint - Description :{0} - Version {1}", MyDAObj.Description, MyDAObj.Version); } Console.ReadLine(); } } } 演示:创建和查询自定义属性信息(续)

  29. 1、将自定义Bugs修复属性和类描述属性合并到一个单一的程序中,使用反射从中获取相关描述数据。1、将自定义Bugs修复属性和类描述属性合并到一个单一的程序中,使用反射从中获取相关描述数据。 主要目的: 掌握属性的定义与使用 掌握使用反射抽取元数据的操作 计划完成时间: 45分钟 学生独立实践

  30. 在本章中,你已经学到: 属性是用来传递关于程序元素,例如类、枚举器和汇编的行为信息到运行时的描述标签。 .NET框架支持两种用于C#程序的属性:预定义和自定义。 预定义属性作为CLR的部分被支持,它们被集成到.NET。 自定义属性是你根据需要创建的属性。 你添加属性的元素被称为属性目标。 反射在运行时获取类型信息的过程中被使用。 反射通常用于完成如下任务: 浏览元数据 完成类型发现 方法和属性的后期绑定 反射发出 小结

  31. 1、编写一程序,利用自定义属性类来对另一个类的代码进行解释说明,并使用反射从中获取解释数据。1、编写一程序,利用自定义属性类来对另一个类的代码进行解释说明,并使用反射从中获取解释数据。 作业

More Related