Tải bản đầy đủ - 0 (trang)
3-13. Create a Custom Attribute

3-13. Create a Custom Attribute

Tải bản đầy đủ - 0trang

CHAPTER 3 ■ APPLICATION DOMAINS, REFLECTION, AND METADATA



programs, particularly the CLR, use this information to determine how to interact with and manage

program elements.

To create a custom attribute, derive a class from the abstract base class System.Attribute. Custom

attribute classes by convention should have a name ending in Attribute (but this is not essential). A

custom attribute must have at least one public constructor—the automatically generated default

constructor is sufficient. The constructor parameters become the attribute’s mandatory (or positional)

parameters. When you use the attribute, you must provide values for these parameters in the order they

appear in the constructor. As with any other class, you can declare more than one constructor, giving

users of the attribute the option of using different sets of positional parameters when applying the

attribute. Any public nonconstant writable fields and properties declared by an attribute are

automatically exposed as named parameters. Named parameters are optional and are specified in the

format of name/value pairs where the name is the property or field name. The following example will

clarify how to specify positional and named parameters.

To control how and where a user can apply your attribute, apply the attribute

AttributeUsageAttribute to your custom attribute. AttributeUsageAttribute supports the one

positional and two named parameters described in Table 3-3. The default values specify the value that is

applied to your custom attribute if you do not apply AttributeUsageAttribute or do not specify a value

for that particular parameter.

Table 3-3. Members of the AttributeUsage Type



Parameter



Type



Description



Default



ValidOn



Positional



A member of the System.AttributeTargets

enumeration that identifies the program

elements on which the attribute is valid



AttributeTargets.All



AllowMultiple



Named



Whether the attribute can be specified more than

once for a single element



False



Inherited



Named



Whether the attribute is inherited by derived

classes or overridden members



True



The Code

The following example shows a custom attribute named AuthorAttribute, which you can use to identify

the name and company of the person who created an assembly or a class. AuthorAttribute declares a

single public constructor that takes a string containing the author’s name. This means users of

AuthorAttribute must always provide a positional string parameter containing the author’s name. The

Company property is public, making it an optional named parameter, but the Name property is read-only—

no set accessor is declared—meaning that it isn’t exposed as a named parameter.

using System;

namespace Apress.VisualCSharpRecipes.Chapter03

{

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly,

AllowMultiple = true, Inherited = false)]



134



www.it-ebooks.info



CHAPTER 3 ■ APPLICATION DOMAINS, REFLECTION, AND METADATA



public class AuthorAttribute : System.Attribute

{

private string company; // Creator's company

private string name;

// Creator's name

// Declare a public constructor.

public AuthorAttribute(string name)

{

this.name = name;

company = "";

}

// Declare a property to get/set the company field.

public string Company

{

get { return company; }

set { company = value; }

}

// Declare a property to get the internal field.

public string Name

{

get { return name; }

}

}

}



Usage

The following example demonstrates how to decorate types with AuthorAttribute:

using System;

// Declare Allen as the assembly author. Assembly attributes

// must be declared after using statements but before any other.

// Author name is a positional parameter.

// Company name is a named parameter.

[assembly: Apress.VisualCSharpRecipes.Chapter03.Author("Allen",

Company = "Apress")]

namespace Apress.VisualCSharpRecipes.Chapter03

{

// Declare a class authored by Allen.

[Author("Allen", Company = "Apress")]

public class SomeClass

{

// Class implementation.

}



135



www.it-ebooks.info



CHAPTER 3 ■ APPLICATION DOMAINS, REFLECTION, AND METADATA



// Declare a class authored by Lena.

[Author("Lena")]

public class SomeOtherClass

{

// Class implementation.

}

}



3-14. Inspect the Attributes of a Program Element Using

Reflection

Problem

You need to use reflection to inspect the custom attributes applied to a program element.



Solution

All program elements implement the System.Reflection.ICustomAttributeProvider interface. Call the

IsDefined method of the ICustomAttributeProvider interface to determine whether an attribute is

applied to a program element, or call the GetCustomAttributes method of the ICustomAttributeProvider

interface to obtain objects representing the attributes applied to the program element.



How It Works

All the classes that represent program elements implement the ICustomAttributeProvider interface. This

includes Assembly, Module, Type, EventInfo, FieldInfo, PropertyInfo, and MethodBase. MethodBase has two

further subclasses: ConstructorInfo and MethodInfo. If you obtain instances of any of these classes, you

can call the method GetCustomAttributes, which will return an object array containing the custom

attributes applied to the program element. The object array contains only custom attributes, not those

contained in the .NET Framework base class library.

The GetCustomAttributes method provides two overloads. The first takes a bool that controls

whether GetCustomAttributes should return attributes inherited from parent classes. The second

GetCustomAttributes overload takes an additional Type argument that acts as a filter, resulting in

GetCustomAttributes returning only attributes of the specified type.

Alternatively, you can call the IsDefined method. IsDefined provides a single overload that takes

two arguments. The first argument is a System.Type object representing the type of attribute you are

interested in, and the second is a bool that indicates whether IsDefined should look for inherited

attributes of the specified type. IsDefined returns a bool indicating whether the specified attribute is

applied to the program element, and is less expensive than calling the GetCustomAttributes method,

which actually instantiates the attribute objects.



136



www.it-ebooks.info



CHAPTER 3 ■ APPLICATION DOMAINS, REFLECTION, AND METADATA



The Code

The following example uses the custom AuthorAttribute declared in recipe 3-13 and applies it to the

Recipe03-14 class. The Main method calls the GetCustomAttributes method, filtering the attributes so

that the method returns only AuthorAttribute instances. You can safely cast this set of attributes to

AuthorAttribute references and access their members without needing to use reflection.

using System;

namespace Apress.VisualCSharpRecipes.Chapter03

{

[Author("Lena")]

[Author("Allen", Company = "Apress")]

class Recipe03_15

{

public static void Main()

{

// Get a Type object for this class.

Type type = typeof(Recipe03_15);

// Get the attributes for the type. Apply a filter so that only

// instances of AuthorAttribute are returned.

object[] attrs =

type.GetCustomAttributes(typeof(AuthorAttribute), true);

// Enumerate the attributes and display their details.

foreach (AuthorAttribute a in attrs) {

Console.WriteLine(a.Name + ", " + a.Company);

}

// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter.");

Console.ReadLine();

}

}

}



3-15. Programmatically Discover the Members of a Type

Problem

You need to determine the members of a type at runtime.



137



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

3-13. Create a Custom Attribute

Tải bản đầy đủ ngay(0 tr)

×