The following code is an example of using WebMethod attribute: [WebMethodDescription="Converts temperature from Fahrenheit to Celsius."] public double TempConvertdouble myTemp TempCon
Trang 1Attributes 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
Trang 3An 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
Applying Attributes
Trang 4Some 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)
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
Trang 5The following code is an example of using DllImport attribute:
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:
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
Trang 6Consider 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:
Trang 7AttributeUsage 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 AllowMultipleproperty 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
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
Event Defined events
Interface Interfaces
Trang 8Member 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,
Trang 9Named parameters are implemented as properties, as shown in the following code snippet:
public string Remarks
It is common to create read-only properties for the positional parameters:
public int 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:
Trang 10AttributeTargets.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
Trang 11public class Calculator
[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)
Calculator MyObj = new Calculator();
Console.WriteLine("The sum of specified two nos are: {0}", MyObj.Add(15,20.5));
1 Select StartÆAll ProgramsÆMicrosoft NET Framework SDK
v2.0ÆToolsÆMSIL Disassembler.
2 Select FileÆOpen The Open dialog box is displayed
3 Select the Attribute_Example.exe file from the Debug folder of the project
4 Click the OK button The IL DASM window is displayed
Trang 125 Expand the Attribute_ExampleÆAttribute_Example.Calculator node, as shown
in the following figure
The IL DASM Window
Trang 136 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 figure
The MetaInfo Window
Trang 14Reflection 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 add types, values, and objects to that application
Reflection is generally used for the following tasks:
Viewing metadata: Allows viewing attribute information from the code at runtime
Performing type discovery: Allows examining the various types in an assembly and
instantiate those types
Late binding to methods and properties: Allows the developer to call properties
and methods on dynamically instantiated objects using type discovery
Reflection emit: Allows you to create new types at runtime and then to use those
types to perform tasks
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 metadata in the Calculator class To do this you need to define an object of the
Calculator class, as shown in the following code statement:
Type type = typeof(Calculator);
In the preceding code statement the typeof operator on the Calculator type, returns an object of the Type type class. The Type class is the root of the reflection class and it is the primary way to access metadata It encapsulates a representation of the type of an object The MemberInfo object of System.Reflection namespace derives from the Type
class that encapsulates information about the members of a class
Then, you need to initiate a call on the GetCustomAttributes() function This function returns an array of objects, each of type BugFixingAttribute.
Retrieving Metadata Using Reflection
Viewing Metdata
Trang 15The 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);
MyBFAObj.Developer);
Console.WriteLine("Date Fixed: {0}",
MyBFAObj.DateFixed);
Console.WriteLine("Remarks: {0}", MyBFAObj.Remarks); }