Visual C++ attributes represent a new philosophy in C++ development. Attributes are designed to allow developers to spend more time focusing on application logic (business logic) and a lot less time focusing on implementation. Attributes don t just help the initial implementer, they also make C++ code easier to read, manage, maintain, and consequently test.
Create a new default ATL Server project with the Project Wizard to see how attributes work. Let s begin again with the .cpp file.
This time you ll notice a few things. First, the handler map is missing. Second, some of the plumbing code that was previously required has been replaced . Instead, there are two uses of attributes. The attributes are marked with square brackets and (in our opinion) fit seamlessly into C++ code. In fact, it s very common that when people first look at the code they don t even realize that there s anything strange about it. The two attributes used are as follows :
[module(name="MyAttributedHandler", type="dll")] [emitidl(restricted)];
The module attribute is used to generate the stub code that s required when creating a DLL (e.g., your DllMain function).
Tip | If you try to create your own DllMain (or other function generated by the module attribute) you ll receive build errors. To solve this problem, you should put this attribute on a class, and then override any of the functions you want by creating them in this class. |
The emitidl attribute is marked as restricted to indicate that IDL shouldn t be generated for this application (you aren t building a COM object!).
If you jump over to the header file, you ll see that things also look different. Your new header file (ignoring ValidateAndExchange , which remains the same) is of the following form:
[request_handler("Default")] class CMyAttributedHandler { [tag_name(name="Hello")] HTTP_CODE OnHello(void) { m_HttpResponse << "Hello World!"; return HTTP_SUCCESS; } };
The request_handler attribute replaces your handler map. You ll see that it takes the string Default as a parameter, and because it s sitting on the CMyAttributedHandler class, it maps the string to this class. It also ensures that the CMyAttributedHandler class derives from CRequestHandlerT , so the code to do this is no longer required.
The replacement method map is also missing. Again, attributes provide the replacement. This time the tag_name attribute, which takes a name parameter of Hello , will do the mapping between this string and its method (the OnHello method on which the attribute sits).
If you try the code, you ll see that it functions in exactly the same way as the previous example. In fact, if you go to the trouble of comparing the output of the compiler, you ll see that the attributed and unattributed applications are identical. So just what are these attributes and what do they do?
You can think of attributes as being like compile-time wizards. They basically generate C++ code for you at compile time. Unlike wizards, attributes can take advantage of knowledge gleaned from your code (from having the front-end of the compiler parse it), thereby making their code spits much more rich, powerful, and customized than those of traditional template-based wizards.
Basically, the compiler parses your code and calls into the attribute provider ( unfortunately , for this release you can t write your own) when it sees an attribute. It informs the attribute provider of what attribute was seen and what its parameters were. Once the parser has reached the end of the appropriate block (e.g., the end of the handler class), it calls back into the attribute provider. The attribute provider can now use information the compiler learned about your class (such as class names, method names , and so on) to inject C++ code into your source. This isn t a template-based code injection ”it s a programmatic-based code injection, which makes the code injection much richer and more powerful than those possible through traditional wizard templates.
You can always view the code generated by the attribute provider by using the /Fx compiler switch. Attributes aren t magic; they merely generate C++ source code (although sometimes the code they generate is extremely complex). This means that whenever you do something with attributes, it s always possible to do the same thing without attributes.
There are attributes designed to make it easier to work with ATL Server Web applications, ATL Server Web services, databases, Perfmon counters, and ATL COM. We touch on many of these attributes throughout the course of this book. The ATL COM attributes in particular may fascinate many ATL developers (but we don t cover them in this book). They re very powerful and flexible, and they enable developers to create a self-registering COM component with just a handful of lines of code.
For the rest of this chapter, you ll continue to use the attributes that you ve seen demonstrated in this section.