Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 24 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
24
Dung lượng
901,81 KB
Nội dung
Attributes and Reflection Chapter 13 Attributes are a simple technique for adding metadata information and behavior to code within applications. You use the reflection technique to pick the attribute related information at runtime. This chapter introduces attributes and reflection and the functions they perform in C# applications. This chapter discusses attribute syntax, and how to use some of the predefined attributes. This chapter discusses also discusses how to create customized user-defined attributes. In addition, this chapter discusses reflection and how to use it to extract attribute related information. In this chapter, you will learn to: Describe attributes Retrieve metadata using reflection Objectives Attributes and Reflection 13.3 ¤NIIT An object is described by the values of its attributes. For example, a car can be described by its make, model, or color. Similarly, a C# program has certain attributes which depict and influence its behavior, for example, compiler instructions. An attribute is a declarative tag that is used to convey information to runtime about the behavior of programmatic elements such as classes, enumerators, and assemblies. A declarative tag is depicted by square ([ ]) brackets placed above the definition of an element such as a class or a method. Attributes are used for adding metadata, such as compiler instructions and other information such as comments, description, methods, and classes to a program. The .NET Framework is equipped with a number of predefined attributes. The code to examine the predefined attributes and act upon the values they contain is also incorporated as a part of the runtime and .NET Framework Software Development Kit (SDK). Attributes are applied to different elements of the code. These elements include assemblies, modules, classes, structs, enums, constructors, methods, properties, fields, events, interfaces, parameters, return values, and delegates. Information about attributes is stored with the metadata of the elements they are associated with. The following syntax enables you to specify an attribute: [attribute(positional_parameters,name_parameter=value, )] element In the preceding syntax, an attribute name and its values are specified within square brackets ([ ]) before the element to which the attribute is applied. Attributes might require one or more parameters, positional or named. Positional parameters are used to specify essential information of an attribute, whereas named parameters are used to convey optional information of an attribute. The .NET Framework supports two categories of attributes to be used in C# programs: predefined and custom. Predefined attributes are supplied as part of the Common Language Runtime (CLR), and they are integrated into .NET. Custom attributes are attributes that you create according to your requirement. Introducing Attributes A pplying Attributes 13.4 Attributes and Reflection ¤NIIT Some commonly used predefined attributes provided with .NET Framework are: Conditional: Causes conditional compilation of method calls, depending on the specified value such as Debug or Trace. For example, it displays the values of variables, when debugging a code. However, this attribute only determines the action that will occur when a method is called. If conditional compilation of a method is required, the #if and #endif directives are used in code. The methods to which you can apply a conditional attribute are subject to a number of restrictions. In particular, they must have a return type of void and must not be marked as an override, and the implementation of the method should be from an inherited interface. For example: [Conditional("DEBUG")] The preceding statement ensures that the target element, whether a class or a method ensures use of that element in debugging mode only. The other value of this attribute can be: [Conditional("TRACE")] WebMethod: Identifies the exposed method in a Web service. A Web service is a Web application that allows you to expose business functionality to other applications. Furthermore, the various properties of this attribute enable you to configure the behavior of the exposed method. The following code is an example of using WebMethod attribute: [WebMethod(Description="Converts temperature from Fahrenheit to Celsius.")] public double TempConvert(double myTemp) { return ((myTemp - 32) * 5) / 9; } The preceding code provides an exposed method of a Web service which converts temperature from Fahrenheit to Celsius. The WebMethod attribute definition above TempConvert() method tells the compiler that it is an exposed method and the Description property of the WebMethod attribute provides information about working of the TempConvert() method. DllImport: Calls an unmanaged code in programs developed outside the .NET environment. An example of such a program is the standard C program compiled into DLL files. By using the DllImport attribute, the unmanaged code residing in DLLs can be called from the managed C# environment. Using Predefined Attributes Attributes and Reflection 13.5 ¤NIIT The following code is an example of using DllImport attribute: using System; System.Runtime.InteropServices; class GenerateBeeps { [DllImport(.kernel32.dll.)] public static extern bool Beep(int f, int d); static void Main() { Beep(1000,111); } } The preceding code uses the Beep() method defined in kernel32.dll and parameters f and d signify the frequency and duration of beep to generate. Obsolete: Enables you to inform the compiler to discard a piece of target element such as a method of a class. For example, when a new method is being used in a class but you still want to retain the old method in that class, as a developer, you can mark the old method as obsolete. You mark the old method as obsolete by displaying a message stating that instead of the old method, the new method should be used. The following code is an example of using Obsolete attribute: using System; public class MyClass { [Obsolete("Don't use the A() method, instead use B() method", true)] static void A() { } static void B() { } public static void Main( ) { A(); } } In the preceding code, the first parameter is string, which contains the message. The second parameter tells the compiler to treat the use of the element as an error. The default value is false, which means compiler generates a warning for this. The .NET Framework allows creation of custom attributes, which can be used to store information and can be retrieved at run time. This information can be related to any target element depending upon the design and the need of an application. Creating Custom Attributes 13.6 Attributes and Reflection ¤NIIT Consider this scenario. A software development company wants to keep track of all the bug fixes as a part of its development process. Although, the company maintains a bug database generated during and after the development process, the program manager wants to attach proper bug fixing reports in code itself. To address this requirement, developers might add comment statements to code. The following code statement displaying a comment is a bug fix example: // Bug # 122 fixed by Sara Levo on 8/12/2006. Although, the preceding comment statement gives some information in the source code, but it gives no direct association to Bug # 122, information of which might be stored in the bug database. In such a situation, the custom attribute can help replace the preceding code statement with the following code statement: [BugFixingAttribute(122,"Sara Levo","8/12/2006") Remarks="Data Type Mismatch at Line 44 "] A simple program can be written to read through the metadata to find the bug fixing notations and to help update the bug database. Metadata is data about data. In other words, it is information that is used to describe other data. To create custom attributes, you need to: 1. Define a custom attribute 2. Name the custom attribute 3. Construct the custom attribute 4. Apply the custom attribute to a target element Defining a Custom Attribute A new custom attribute class is derived from the System.Attribute system class, as shown in the following code: public class BugFixingAttribute : System.Attribute You need to then apply the attribute target using a predefined attribute to the new custom attribute class, AttributeUsage, as shown in the following code statement: [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] The AttributeUsage attribute allows two arguments. One argument is a set of flags that indicates the target element. To continue with the bug fixing example, the Attributes and Reflection 13.7 ¤NIIT AttributeUsage attribute will be the class and its constructor, fields, methods, and properties. The other argument is a flag that indicates whether a given element might be applied with more than one such attribute. In the preceding code, the AllowMultiple property is set to true, indicating that more than one BugFixingAttribute can be applied to class and its members. Besides the AllowMultiple property there are other properties that can be used with the attributes. These properties are: Inherited: A boolean value “true” for this property indicates that if an attribute is applied to base class and all its derived classes. A value of “false” stops the attribute when it is applied to a subclass. ValidOn: This property helps define the target elements on which the custom attribute can be applied. The element to which you attach an attribute is called an attribute target. The AttributeTargets enumerator is used for setting all the possible attribute targets. The following table lists the various member names of the AttributeTargets enumerator. Member Name Attribute Targets All Elements including assembly, class, class member, delegate, enum, event, field, interface, method, module, parameter, property, or struct Assembly Assembly only Class Instances of the class ClassMembers Classes, structs, enums, constructors, methods, properties, fields, events, delegates, and interfaces Constructor Class constructors Delegate Delegate methods Enum Defined enumeration Event Defined events Field Fields Interface Interfaces 13.8 Attributes and Reflection ¤NIIT Member Name Attribute Targets Method Defined methods Module A single module Parameter Parameters of a method Property Properties (both get and set, if implemented) Struct Structs AttributeTargets Enumerator Naming the Custom Attribute Let us continue with the bug fixing example in which the new custom attribute is named as BugFixingAttribute. The normal convention is to append the word Attribute to the attribute name. The compiler supports appending by allowing you to call the attribute with the shorter version of the name. Therefore, the attribute can be written as shown in the following code statement: [BugFixing(122,"Sara Levo","8/12/2006") Remarks="Data Type Mismatch at Line 44 "] The compiler first looks for the definition of an attribute named BugFixing. When it does not find the definition it looks for the definition with the name, BugFixingAttribute. Constructing the Custom Attribute Every attribute must contain at least one constructor. In the following bug fixing example, the bug number, developer's name, and fixed date are positional parameters and remarks is a named parameter. Positional parameters are passed through the constructor in the order declared in the constructor, as shown in the following code snippet: public BugFixingAttribute(int BugNo, string Developer, string DateFixed) { this.BugNo = BugNo; this.Developer = Developer; this.DateFixed = DateFixed; } Attributes and Reflection 13.9 ¤NIIT Named parameters are implemented as properties, as shown in the following code snippet: public string Remarks { get { return Remarks; } set { Remarks = value; } } It is common to create read-only properties for the positional parameters: public int BugNo { get { return BugNo; } } Applying the Custom Attribute The attribute can be applied by placing it immediately before its target. To test the BugFixAttribute attribute for the preceding example, you can create a program for a simple class named Calculator and give it four functions. You need to assign the BugFixAttribute to the target element class to record its code-maintenance history, as shown in the following code snippet: [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 The BugFixAttribute attribute will be stored with the metadata. The following code shows the complete listing of the bug fixing program: using System; using System.Reflection; namespace Attribute_Example { // create a custom attribute to be assigned to class and its members [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | 13.10 Attributes and Reflection ¤NIIT AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] 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; } } } [BugFixingAttribute(125,"Sara Levo","08/15/06", Remarks="Return object not specified")] [BugFixingAttribute(159,"Sara Levo","08/17/06", Remarks="Data Type Mismatch")] [...]... NIIT Attributes and Reflection 13.23 Exercises Exercise 1 Write a program, to create BugFixingAttribute custom attribute to be assigned to class members and DescriptionAttribute custom attribute to be assigned to class members Merge the Bugs Fixing attribute and Class description attribute together in a single application and use reflection to retrieve data from the same 13.24 Attributes and Reflection. .. types to perform certain tasks For example, an assembly can be defined to execute dynamically or 13.16 Attributes and Reflection NIIT to save itself to disk Furthermore, reflection emit enables you to define new modules and new types with methods NIIT Attributes and Reflection 13.17 Activity: Creating and Querying Custom Attribute Information Problem Statement John is a developer in a software development... IL DASM window is displayed NIIT Attributes and Reflection 13.11 5 Expand the Attribute_Example in the following figure Attribute_Example.Calculator node, as shown The IL DASM Window 13.12 Attributes and Reflection NIIT 6 Press CTRL+M The MetaInfo window is displayed The MetaInfo window displays the complete metadata information containing the created BugFixing custom attributes, as shown in the following... containing the custom attributes? 13.22 Attributes and Reflection NIIT Summary In this chapter, you learned that: An attribute is a declarative tag that is used to convey information to runtime about the behavior of programmatic elements such as classes, enumerators, and assemblies The NET Framework supports two categories of attributes to be used in C# programs: predefined and custom Predefined attributes are... Window NIIT Attributes and Reflection 13.13 Retrieving Metadata Using Reflection Reflection is used in the process of obtaining type information at runtime The classes that give access to the metadata of a running program are in the System .Reflection namespace The System .Reflection namespace contains classes that allow programmers to obtain information about the application that is running and to dynamically... using type discovery Reflection emit: Allows you to create new types at runtime and then to use those types to perform tasks Viewing Metdata To view metadata using reflection, the MemberInfo object of the System .Reflection namespace needs to be initialized This object helps discover the attributes of a member and to provide access to metadata Taking the bug fixing example further, use reflection to read... CLR, and they are integrated into NET Custom attributes are attributes that you create according to your requirement The element to which you attach an attribute is called an attribute target Reflection is used in the process of obtaining type information at runtime Reflection is generally used for the following tasks: Viewing metadata Performing type discovery Late binding to methods and properties Reflection. .. foreach (Object attributes in type.GetCustomAttributes(false)) { DescriptionAttribute MyDAObj = (DescriptionAttribute )attributes; Console.WriteLine("\nClass : EntryPoint Description :{0} - Version {1}", MyDAObj.Description, MyDAObj.Version); } 13.20 Attributes and Reflection NIIT } } } Console.ReadLine(); Task 2: Building and Executing an Application To build and execute the application, John needs to... Console.WriteLine("Remarks: {0}", MyBFAObjM.Remarks); } } Console.ReadLine(); Attributes and Reflection 13.15 The preceding code prints all the bug fixing related information defined using attributes The following figure displays the output of the preceding code Output of the Modified Main() Method Performing Type Discovery Reflection also helps to explore and examine the contents of an assembly It helps find the types... 13.14 Attributes and Reflection NIIT The following code shows the modified Main() method of the bug fixing example: 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 . attributes are attributes that you create according to your requirement. Introducing Attributes A pplying Attributes 13.4 Attributes and Reflection ¤NIIT Some commonly used predefined attributes. displayed. 13.12 Attributes and Reflection ¤NIIT 5. Expand the Attribute_ExampleÆAttribute_Example.Calculator node, as shown in the following figure. The IL DASM Window Attributes and Reflection. Binding to Methods and Properties Reflection Emit Attributes and Reflection 13.17 ¤NIIT to save itself to disk. Furthermore, reflection emit enables you to define new modules and new types with