Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
180
Добавлен:
24.05.2014
Размер:
26 Мб
Скачать

600 Project 5 CREATING A COM COMPONENT USING ATL

It allows for easy derivation from base classes without cumbersome and elaborate implementation details.

It uses inserted code, which is recognized by the debugger, unlike the macros that were used earlier.

It replaces a large amount of IDL code required by a COM component with very few concise attributes.

their proper usage. These characteristics areYreferred to as the context of the attribute. For example, the cpp_quote attribute can be inserted anywhere within a

It uses a familiar and simple calling convention.

Similar to most C++ constructs, attributes have some characteristics that define

 

C++ source file, while the coclass attribute can only be applied to an existing

 

class.

 

L

 

 

F

 

 

 

 

 

 

M

 

 

TIP

A

 

 

 

E In the Integrated DevelopmentT nvironment (IDE), the attributes are supported by the

wizards and by the properties window.

In Visual C++ .NET, a compiler is able to dynamically parse and verify attributes during compilation once it recognizes the presence of attributes in a source file. When a project is built, the compiler produces an object file as a result of having parsed each C++ source file. However, whenever a compiler encounters an attribute, it is parsed and verified syntactically. In the next step, the compiler calls an attribute to insert code or make modifications at compile time. The implementation of providers differs depending on the types of attributes.

However, usage of attributes does not make any changes in the contents of a source file. The generated attribute code is visible only during debugging sessions of code. It is also possible to generate a text file displaying the results of attribute substitution, for each source file in a particular project.

Custom Attributes

Besides the predefined categories of attributes, you can also define your own attributes. Such attributes are called custom attributes. They allow metadata to be user-extensible. Using custom attributes is a simple way of extending the meta-

Team-Fly®

INTRODUCTION TO ATTRIBUTE BASED PROGRAMMING Chapter 18 601

data of any given managed element. Custom attributes are stored with the metadata to record application-specific information that can be accessed at run time. These are supported in all the languages that target the .NET Framework, such as C# and Visual Basic .NET.

All custom attributes are derived directly or indirectly from the class Attribute. Attributes can be applied to a target element, and multiple instances of an attribute can be applied to the same target element. In addition, attributes can be inherited by an element that is derived from the target element. Compilers use the information associated with attributes to determine if they are custom attributes.

For example, you can create a custom attribute that you can use to embed details, such as the name of the programmer of a class or a method, date on which the class was created, date on which it was revised and so on, in the compiled application. An example of using a custom attribute follows:

[AuthorAttribute(“Created”,”John Doe”,”12/12/2001”)]

[AuthorAttribute(“Revised”,”John Doe”, “12/14/2002”)]

public __gc class someClass

{

}

NOTE

The information stored in the attribute in the preceding example can also be provided using comments, but as you will see later, encoding them in an attribute also allows programmatic retrieval of the data from a compiled application.

You define custom attributes by deriving types from the Attribute class. The Attribute class includes methods that are used to access and test custom attributes.

The following are the steps that need to be followed to design custom attribute classes:

1.Apply the AttributeUsage attribute.

2.Declare the attribute class.

602Project 5 CREATING A COM COMPONENT USING ATL

3.Declare constructors.

4.Declare properties.

I will now discuss the steps to create the custom attribute used in the preceding example.

A new attribute can be created by creating a class which derives from the class System::Attribute as shown in the following code snippet:

public __gc class AuthorAttribute: public System::Attribute

{

}

Since the attribute has to store three strings, the class will have three properties . To store the values for the properties, you need to declare three variables in the class, as shown in the following code snippet:.

public __gc class AuthorAttribute: public System::Attribute

{

private:

String *m_Comment;

String *m_Author;

String *m_Date;

}

Each of the properties will have a pair of get, set methods. The get, set method pair for the Comment property is shown below:

__property String * get_Comment()

{

return m_Comment;

}

__property void set_Comment(String *value)

{

m_Comment=value;

}

You will create similar methods for the other two properties. The constructor for the attribute class will initialize the properties once an attribute is created. The following is the code for the constructor:

INTRODUCTION TO ATTRIBUTE BASED PROGRAMMING Chapter 18 603

AuthorAttribute(String *Comment, String *Author, String *Date)

{

this->Comment=Comment; this->Author=Author; this->Date=Date;

}

The last step is to define what elements can use this attribute. This is done using an attribute as shown in the following code snippet:

[AttributeUsage(AttributeTargets::Class | AttributeTargets::Method | AttributeTargets::Property,

AllowMultiple = true)]

public __gc class AuthorAttribute: public System::Attribute

{

//....

}

In the preceding code, the attribute AttributeUsage defines that the AuthorAttribute can be used with classes and methods, and properties of classes. Once compiled, this attribute can be used to supply the creation information of classes. If this attribute needs to be used in different projects, then it can be compiled into a class library and put into the global assembly cache (details of which you will read in Chapter 25).

Reflection

Reflection is used to retrieve the metadata stored using attributes. Reflection can be used to create an instance of a type dynamically besides binding the type to an existing object or getting the type from an existing object. The methods of a type or its fields and properties are then invoked. Reflection also provides certain objects that encapsulate assemblies, types, and modules. Reflection is useful for the following:

Used by applications that need to retrieve metadata.

604Project 5 CREATING A COM COMPONENT USING ATL

Used to detect types declared in an assembly at run time and instantiate those types.

Used for late binding to methods and properties.

Next, you will take a look at how reflection can be used to retrieve metadata and to detect types at runtime.

For illustrating the metadata retrieval, I will use a class in which the metadata is encoded using the AuthorAttribute attribute (that you created in the preceding section). The definition of the class is as follows:

[CustomAttrib::AuthorAttribute(“Created”,”John Doe”,”12/12/2001”)]

[CustomAttrib::AuthorAttribute(“Revised”,”John Doe”,”12/14/2001”)]

public __gc class Class1{ int i;

//....

};

Assume that the class Class1 is compiled into a DLL. Now, to access the metadata for Class1, you will use reflection. To do so, you will use the MemberInfo class in the System::Reflection namespace. This class has a method GetCustomAttributes that returns an array of attributes. The method takes two parameters. The first parameter is the type of the attribute and the second parameter is a Boolean value, which indicates whether to search in the current class’s inheritance chain for the attribute. The following code depicts the syntax:

Object *attribs[];

MemberInfo *inf = __typeof(Class1);

attribs=inf->GetCustomAttributes(__typeof(AuthorAttribute), false);

In the preceding code, the GetCustomAttributes method returns an array of AuthorAttribute attributes for the class Class1. After the array of attributes is recovered, display the metadata in each of the AuthorAttributes as shown in the following code:

int i=0;

while(i<attribs.Length)

{

Object *att;

INTRODUCTION TO ATTRIBUTE BASED PROGRAMMING Chapter 18 605

att= attribs[i]; AuthorAttribute *aObj; aObj=(AuthorAttribute *) att;

Console::Write(aObj->Author);

Console::Write(aObj->Comment);

Console::Write(aObj->Date);

i++;

}

Now that you have seen how to access metadata from assemblies using reflection, I will describe briefly the way to access types declared in an assembly and accessing the members of a type.

Suppose a program needs to retrieve a list of all types in the System.Drawing.dll assembly, it can do so using the following code:

Assembly *a = Assembly::LoadFrom(“e:\\winnt\\microsoft.net\\framework\\v1.0.3328\\System.Drawing.d ll”);

Type *types[] = a->GetTypes( ); i=0;

while(i<types.Length)

{

Type *t=types[i];

Console::WriteLine(t->ToString());

Console::Write(i);

i++;

}

The preceding code first loads the assembly using the static method LoadFrom of the Assembly class by passing the complete path to the DLL. After the assembly is loaded, the GetTypes method of the Assembly class is used to retrieve a list of all types in the DLL and then they are displayed on the screen.

Reflection also supports exploring any of these types in detail. For example, you can retrieve a list of all the members of a type or you can retrieve a list of all the methods supported by a particular type. The following code lists all the methods in the type Pen in the System::Drawing assembly.

Type *tpe=types[9]; //the 10th type in the array

MemberInfo *mInfArr[] = tpe->GetMethods();

606 Project 5 CREATING A COM COMPONENT USING ATL

i=0;

while(i<mInfArr.Length)

{

MemberInfo *m=mInfArr[i];

Console::WriteLine(m->Name); i++;

}

Similarly the details of each method, such as the parameters and the data type of each parameter, can be displayed using reflection.

Summary

In this chapter, you looked at the usage of two new features, namely attributes and reflection. You saw how attributes can be used to add metadata and how reflection can be used to retrieve the metadata and also explore assemblies dynamically at runtime. In most of the projects you will create henceforth, you will find that attributes significantly reduce your coding efforts.

Chapter 19

Implementing

COM Using ATL

Having acquired the basic knowledge of COM and COM+ services in Chapter 10, you will next proceed to learn to create an ATL-based COM server.

In this chapter, you will be developing a project that illustrates the use of ATL in creating COM components. Before getting into the intricacies of ATL programming, this chapter first introduces you to the scenario for which you will design the project. Then, you will go through the tasks performed in different phases of the project life cycle and learn about the design of the project. Finally, you will be taken through the steps required to create the project.

Art-Shop – An Online Art Gallery

Art-Shop is an art gallery based in New York City that showcases and sells artwork, such as paintings, woodcarvings, sketches, and metal works. Currently, ArtShop has four galleries located in three states, Utah, California, and Wyoming, in addition to the one in New York City. It has been riding high until recently because of its innovative methods, one of which is its initiative to locate and popularize the works of lesser-known artists from smaller towns. Lately, Art-Shop has been facing considerable competition in this arena. To counter this, the management of the firm held a meeting to devise some ways to further increase its growth in order to maintain its position amidst this growing competition. After a brainstorming session, the stakeholders concluded that the best way to expand their business is by going online. To do this, they contracted Code-Forge, a New York–based enterprise solutions company, to design and construct the online site, www.art-shop.com.

Project Life Cycle

The development life cycle of a project, as discussed in Chapter 8, usually involves three phases:

Project initiation

Project execution

Project deployment

IMPLEMENTING COM USING ATL

Chapter 19

609

 

 

 

 

In Art-Shop’s project-initiation phase, the project plan was prepared and the development team for the project was identified. The development team further prepared a comprehensive list of tasks involved in the execution and the deployment phases of the project’s life cycle.

The project is now in the second phase, the project execution phase, and the team has currently constructed the “home page” of the site. I will first discuss the design of the site’s home page, and in the section following that I will introduce you to the activities planned for designing the Checkout page.

Design of the Site

The home page of Art-Shop’s site lists the various categories of art available in its art gallery. Visitors to the site can browse through the art available under each of these categories and obtain details about the art, such as the name of the artist and the price of the artwork. Visitors can also place an order for the art, if required. In addition to these basic facilities, the home page also provides various other features, such as a newsletter, a feedback form, and a guest book. This newsletter is used to provide an update of the latest happenings in the field of arts. The feedback page enables Art-Shop to gather feedback from customers, which can then be used to enhance the site. The guest book feature provides a common “room” in which people who are interested in art can express their views.

When a purchase is made at the site, the visitor is taken to the checkout page where the visitor can enter his/her credit card number. The credit card number will be validated before an order is placed.

The catalog portions of the site, which display the art on sale, is ready. The next step for the Code-Forge team is to create a checkout page where a visitor can make a purchase.

The Checkout Page

As specified earlier, Art-Shop’s site enables visitors to purchase art objects online by credit card. To implement this feature, the Code-Forge team decided to create a checkout page. A visitor can make a purchase at the checkout page by entering his/her credit card number. The following are the tasks performed by the development team during the project execution phase to design the checkout page:

Requirements analysis

Design