Using Predefined Attributes


In this section, we’ll discuss how to use the attributes that are predefined by the .NET Framework. You can use these attributes in two ways: by editing the AssemblyInfo.cpp file that comes as part of a managed C++ project, and by attaching attributes to managed elements in your code.

The AssemblyInfo.cpp File

Every managed C++ project includes an AssemblyInfo.cpp file that contains code affecting the attributes applied to the assembly. You can edit this file to customize the assembly attributes, which will be used to set the metadata in the assembly at build time. The following exercise shows you how to modify assembly attributes:

  1. Create a new Visual C++ Console Application (.NET) project called AssemblyAttributes.

  2. Open the AssemblyInfo.cpp file and examine its contents. You’ll see that the file contains a number of entries of the form:

    [assembly:AssemblyTitleAttribute("")];

    Most of these have empty strings as arguments.

  3. Find the version number attribute and edit it to produce a new version:

    [assembly:AssemblyVersionAttribute("1.1.105.3")];

    This number would correspond to version 1.1, build 105, revision 3.

  4. Compile and build the program. If you now look at the assembly using the ILDASM tool, you can see the version in two places. First, it will show in the pane at the bottom of the ILDASM main window:

    click to expand

    You can also see it by double-clicking on the MANIFEST entry in the main window and scrolling down to the bottom of the data window, which is opened. The line within the .assembly AssemblyAttributes block starting with .ver lists the version metadata:

    .ver 1:1:105:3

You can check this version number in applications that use this assembly, but explaining how is beyond the scope of this book.

Using the Predefined Attribute Classes

Although much of the metadata produced by the compiler is predefined and you can’t alter it, a number of optional standard attributes are provided by various .NET Framework namespaces. The following table lists some of the standard attributes you might want to use in your own projects:

Class

Description

System::AttributeUsageAttribute

Specifies the usage of another attribute class

System::CLSCompliantAttribute

Indicates whether a program element is CLS-compliant

System::Diagnostics::ConditionalAttribute

Indicates that a method can be called if a preprocessor symbol is defined

System::Diagnostics::DebuggableAttribute

Modifies code generation for run- time JIT (Just-In-Time) debugging

System::Diagnostics::DebuggerHiddenAttribute

Applied to a method to indicate that breakpoints can’t be set in the code, and that debuggers will not stop in the method

System::Diagnostics::DebuggerStepThroughAttribute

Applied to a method to indicate that the debugger will not stop in this method, although breakpoints can be set

System::FlagsAttribute

Indicates that an enumeration is to be used as a set of flags and can be represented by a bit field

System::MTAThreadAttribute

Indicates that the default COM threading model for an application is MTA (multi-threaded apartment)

System::NonSerializedAttribute

Indicates that a field of a serializable class should not be serialized

System::ObsoleteAttribute

Indicates program elements that are no longer in use

System::ParamArrayAttribute

Indicates that a method accepts a variable number of arguments

System::SerializableAttribute

Indicates that a class can be serialized

System::STAThreadAttribute

Indicates that the default COM threading model for an application is STA (single-threaded apartment)

You’ll meet a lot of attributes when working with COM in managed C++ because they are used to define all the metadata needed by COM objects that is specified in IDL for unmanaged COM C++ code.

The following exercise will show you how to use one of the standard attributes in code. You’ll use the ObsoleteAttribute class to mark a class method as obsolete and see how the compiler gives a warning when you use the obsolete method. This exercise will also show you how to build a managed C++ dynamic link library (DLL) and use it in code. If you want to know more about DLLs, see the next sidebar in this chapter, “DLLs in Windows.”

start sidebar
DLLs in Windows

Windows executable code can be parceled in two forms: as an executable, or as a DLL. Dynamic link libraries contain executable code but can’t run on their own. A DLL contains functions or classes used by other code in a process, and a DLL is loaded at run time so that the function or class code is accessible.

There are both advantages and disadvantages to using DLLs. Here are some advantages:

  • DLLs can be loaded and unloaded on demand, so applications can control their memory use.

  • They can be shared by more than one process, so they are a good way to provide shared functionality such as printer drivers.

  • Using DLLs means that it is possible to upgrade or fix part of an application without having to redistribute or reinstall everything.

There is also one major drawback to DLLs in the traditional Windows world: an application might use the wrong version of a DLL. This is especially true of Windows system DLLs, because you can easily end up with multiple versions of the same DLL on one computer. This can lead to problems that are hard to debug and users with applications that don’t work because somewhere a DLL is out of date.

However, using the wrong version of a DLL isn’t much of a problem for .NET programmers because assemblies—the fundamental building blocks of .NET applications—have version information built in, and it is possible to specify in the code exactly what versions of an assembly are acceptable. If code does end up running on a computer with the wrong version of an assembly, the result will be a precise error message rather than odd behavior.

In the .NET world, DLLs provide one way to package up assemblies. If an assembly contains a standard entry point such as main or WinMain, it is built as an executable with an .exe extension and can be executed from the command line. If the assembly doesn’t contain an entry point, it is built as a library assembly with a .dll extension. A library assembly has no entry point to begin execution, but contains types that can be referenced from other assemblies.

end sidebar

Note

The compiler recognizes only the Obsolete attribute in managed types that have been loaded from a separate assembly. If you put all the code from the exercise into one file and build a single executable, you’ll find that the compiler doesn’t act on the ObsoleteAttribute settings.

The Solution consists of two projects: a Console Application that holds the _tmain function, and a Class Library project that holds a managed class called Hello. The _tmain function will create a Hello object and call methods on it, both of which require that the DLL assembly be loaded at run time.

  1. Create a new Visual C++ Console Application (.NET) project and call it UseAttributes. You’ll add code to this project later.

  2. Right-click on the Solution name in Solution Explorer, choose Add from the shortcut menu, and then New Project. This will bring up the familiar New Project dialog box.

    click to expand

  3. Select Visual C++ Projects in the Project Types pane. Next, make sure the project type is set to Class Library (.NET), and call the project MyDll. Click OK.

  4. Open the MyDll.h file from Solution Explorer.You’ll see the skeleton of a namespace containing a single class. Edit the class definition so that it contains two methods, as shown here:

    // MyDll.h #pragma once using namespace System; namespace MyDll { public __gc class Hello { public: [ObsoleteAttribute(S"Don’t use this", true)] void SayHello() { Console::WriteLine(S"Hello"); } void SayHello2() { Console::WriteLine(S"Hello again"); } }; } 

    The two methods simply write a line of text to the Console. The difference between them is that the first has an ObsoleteAttribute attached to it, indicating that this method is out of date and shouldn’t be used. The first argument to ObsoleteAttribute is a string giving the reason the method is obsolete and telling the user what alternative action to take. Many compilers (although unfortunately not Microsoft Visual C++) will display this string as part of a compiler warning or error message. The second argument is a Boolean value that determines whether use of this function is to be regarded as an error (true) or a warning (false) by the compiler, although this argument is also ignored by the Visual C++ compiler.

  5. Build the DLL project by right-clicking on the project name in Solution Explorer and choosing Build from the shortcut menu.

  6. Open the UseAttributes.cpp source file. Because the Hello class is located in another assembly, you need to add a #using statement so that the compiler can locate the assembly at compile time. Add the following line immediately after the existing #using statement:

    #using <MyDll.dll>

    It will also be easier to use the Hello class if you don’t have to use fully qualified names, so add a using declaration for the namespace:

    using namespace MyDll;
  7. Edit the _tmain function to create an object and call the obsolete method:

    int _tmain() { Console::WriteLine(S"Attribute test"); Hello* ph = new Hello(); ph->SayHello(); return 0; } 
  8. Build the project. The compiler will see the ObsoleteAttribute attached to the SayHello method and issue a compiler warning:

    UseAttributes.cpp(19) : warning C4996: ’MyDll::Hello::SayHello’ was declared deprecated

Managed C++ doesn’t treat ObsoleteAttribute quite the same way as the C# and Microsoft Visual Basic .NET compilers do: it doesn’t print the message associated with the attribute and it takes no notice of the second parameter, flagging all obsolete methods as warnings only.




Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
EAN: N/A
Year: 2003
Pages: 208

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net