Chapter 15. The .NET Framework Class Library

After completing this chapter, you will be able to:

  • Identify the components of the Microsoft .NET Framework.

  • Work with the major components of the .NET Framework.

  • Recognize the main namespaces that make up the .NET Framework class library.

In previous chapters, you learned how to use C++/CLI to build simple applications. Now, it’s time to move on to learn how to build real Microsoft .NET applications that involve GUIs, databases, web servers, and all the other mechanisms needed by the modern Microsoft Windows application. And that’s where the .NET Framework comes in.

The .NET Framework is the library of classes that you use to build Windows applications. It is large, complex, and far-reaching in its scope. This chapter gives you an overview of what the .NET Framework is and what it can do before we cover some of its features in more detail in later chapters.

What is the .NET Framework?

The .NET Framework is a computing platform that has been designed by Microsoft to simplify the development of modern applications, such as the following:

  • Applications that use sophisticated GUI front ends

  • Applications that use the Internet

  • Applications that are distributed over more than one computer

  • Applications that make use of databases and other data sources

There are two main components to the .NET Framework: the Common Language Runtime and the .NET Framework class library. You’ll examine both components in this chapter.

The Common Language Runtime

You’ve already met the Common Language Runtime (CLR) because this is the part of .NET that manages your code as it runs, providing services such as garbage collection. The CLR is a run-time execution engine that is responsible for executing code within the .NET environment, providing services such as security, memory management, and remoting (communication between objects in different domains, processes, or computers). Code that is run by the CLR is known as managed code; code that executes outside the control of the CLR is unmanaged code. All Microsoft Visual Basic and C# code is managed, but it’s possible to write both managed and unmanaged code in Microsoft Visual C++ and to have both types of code working together in the same application.

The Microsoft Intermediate Language

All .NET languages compile down into an intermediate form called Microsoft Intermediate Language (MSIL, or just IL.)

IL is similar to Java bytecode in that it’s an intermediate form of code produced by the compiler that can’t be directly executed on a target system. IL code is also portable and is always converted into native code before it’s executed, which is done by a Just-In-Time (JIT) compiler. This conversion might happen on demand, function-by-function as an application executes, or all at once when an application is installed.

One of the great innovations of IL is that it isn’t simply a low-level, machine-independent object code. In fact, support for object-oriented functionality—such as the ideas of classes, encapsulation and data-hiding, polymorphism, and inheritance—is built into IL, so you can view it as a type of object-oriented assembler language. This functionality makes it far more powerful than Java bytecode, and it makes it possible for you to perform cross-language object-oriented programming, easily calling members in C++/CLI classes from Visual Basic, and vice-versa, and even inheriting from a C++/CLI class in Visual Basic.

Note

If you’re interested in seeing what IL looks like, you can use the IL Disassembler tool, ILDASM, to open a .NET executable and show you the code in IL. There’s an example of how to do so in the section Metadata later in the chapter.

The Common Type System

The Common Type System (CTS) provides a specification for how types are defined, managed, and used, which is an important part of the .NET cross-language integration. The CTS provides a set of rules that languages must obey, which helps to ensure that types created in different languages can interoperate with one another.

The Common Language Specification

The Common Language Specification (CLS) is a set of rules and constraints that compiler and library writers need to follow to ensure that the languages and code they produce will interoperate with other .NET languages. The CLS forms a subset of the CTS, and if a language or a library is CLS-compliant, it will completely interoperate with other CLS-compliant languages.

You’ll see in the online documentation that some .NET member functions are marked as not CLS-compliant, which means that they might not be accessible from some .NET languages. For example, functions that use unsigned integers are not CLS-compliant because unsigned integers aren’t supported by Visual Basic. As a result, unsigned integers are not included in the types specified by the CLS.

The .NET Framework class library

The .NET Framework class library is an object-oriented library of classes that provides all the tools you need to write a wide variety of applications.

Since Windows was first released, programmers have written Windows applications using the Windows API (application programming interface). This API gives you a large number of C functions—several thousand, in fact—that you can call from your applications to interact with Windows. However, there are two main problems with the Windows API: first, it isn’t object-oriented, and second, it’s a C library, so it can’t easily be used from every language.

One of the benefits of object-oriented programming is the help that it gives in structuring and managing large-scale projects. The Windows API has grown to several thousand functions, and it becomes harder and harder to manage such a large collection of unstructured routines. In addition to its other benefits (such as encapsulation and polymorphism), object-oriented programming lets you impose a structure on code. So, for example, a Dialog class can contain all the functions relating to dialog boxes. This ability makes it much easier to use a library the size of the Windows API.

The second problem with the Windows API is that it’s basically written for C programmers, so it uses many features that are unique to C, such as pointers and null-terminated strings, which makes it hard—and sometimes impossible—to use some functionality from languages other than C or C++. You also tend to need a lot of ugly “plumbing” to interface between languages such as Visual Basic and the API.

The .NET Framework class library provides a set of classes that can be used from any .NET language because it works at the IL level. All .NET languages compile down to the same intermediate code, and because they all use references and agree on the basic set of value types, they can all use the classes defined in the class library. This is a huge advantage and provides language interoperability on a scale never seen before.

Assemblies

Assemblies are the basic building blocks with which .NET applications are constructed, and they’re the fundamental unit of deployment and versioning. Assemblies contain IL code, metadata that describes the assembly and its contents, and any other files needed for run-time operation. An assembly is therefore much more self-contained than a standard Windows executable or Component Object Model (COM) object because there is no reliance on external sources of information such as the Windows Registry. Every .NET type is part of an assembly, and no .NET type can exist outside an assembly.

There are several aspects by which assemblies are fundamental to the .NET world:

  • Versioning The assembly is the smallest unit to which versioning is applied, and the assembly manifest describes the assembly’s version together with the versions of any assemblies on which it depends. This information means that it’s possible to check that components with the wrong version information aren’t being used at run time.

  • Deployment Assemblies are loaded only as needed, which makes them highly suitable for distributed applications.

  • Type A type’s identity includes the assembly in which it resides. Two types with the same name living in two different assemblies are considered to be two completely different types.

  • Security The boundary between assemblies is where security permissions are checked.

Metadata

.NET classes are self-describing, which means that they carry descriptive information with them in the .exe or .dll file. This information, called metadata, includes the following:

  • The name, version, and culture-specific information (such as the language and calendar used) for the assembly

  • The types that are exported by the assembly

  • Other assemblies on which this one depends

  • Security permissions needed to run

  • Information for each type in the assembly: name, visibility, base class, interfaces implemented, and details of members

  • Additional attribute information

Most of the metadata is standard and is created by the compiler when it produces the IL code, but you can use attributes to add extra metadata information.

The following exercise shows you how to modify the standard metadata produced by the compiler.

  1. Start Microsoft Visual Studio 2012 and create a new CLR Console Application project named Meta1.

  2. Open Solution Explorer and look at the Source Files folder.

    You can see that the project contains three C++ source files: Meta1.cpp is the code for the application, AssemblyInfo.cpp contains definitions of the standard metadata items that you can modify, and StdAfx.cpp is there to include the StdAfx.h header file.

  3. Open AssemblyInfo.cpp.

    The file contains a number of lines that look like the following:

    [assembly:AssemblyTitleAttribute("Meta1")];
    [assembly:AssemblyDescriptionAttribute("")];
    [assembly:AssemblyConfigurationAttribute("")];
    [assembly:AssemblyCompanyAttribute("")];
    [assembly:AssemblyProductAttribute("Meta1")];
    [assembly:AssemblyCopyrightAttribute("Copyright (c)  2012")];
    [assembly:AssemblyTrademarkAttribute("")];
    [assembly:AssemblyCultureAttribute("")];

    Metadata is added to C++ code by enclosing declarations in square brackets ([]). Metadata is most often attached to code to describe classes and functions. Here, the keyword assembly: at the start of the attribute means that this attribute applies to an assembly, as opposed to being attached to code. There’s a set of standard attributes that you can use to change the metadata compiled into an assembly, and most of them are listed in AssemblyInfo.cpp.

  4. Edit the AssemblyCompanyAttribute line to contain some suitable name, such as the following:

    [assembly:AssemblyCompanyAttribute("City Power & Light")];
  5. Build the project, which automatically creates the assembly for you. How can you be sure that the metadata in the assembly reflects your change? One way to find out is to use ILDASM, which is part of the .NET SDK. On my system, this is located in the folder Program Files (x86)Microsoft SDKsWindowsv8.0AinNETFX 4.0 Tools.

    Note

    I am using a prerelease version of Windows 8 and Visual Studio 2012, so the location of ildasm.exe might be different on your system.

  6. When the ILDASM window opens, use the File menu to navigate to the Meta1.exe executable and open it. You should see something like the screen shot that follows.

    A screenshot of the ILDASM window, displaying the structure of a .NET EXE or DLL file in a tree structure. There are many entries for a C++/CLI file. The MANIFEST is the first item in the tree.
  7. Double-click MANIFEST, which opens a separate window displaying the assembly metadata.

    At the top of this listing are the details of the assemblies on which this executable depends. Scroll down until you find the AssemblyCompanyAttribute line, which should read something like the following:

    .custom /*0C000005:0A000009*/ instance void
                                         ['mscorlib'/* 23000001 */]
    'System.Reflection'.'AssemblyCompanyAttribute'
    /* 0100000D */::.ctor(string) /* 0A000009 */
    = ( 01 00 16 41 63 6D 65 20 52 6F 63 6B 65 74 20 53
                                                // ...City Power &
        6C 65 64 2C 20 49 6E 63 2E 00 00 )      // Light...

    Although the contents are presented in hexadecimal, you can see that the metadata does reflect the change you made to the project.

The .NET Framework namespaces

The .NET Framework class library is made up of a set of classes, interfaces, structures, and enumerations that are contained in over 400 namespaces. This section begins by explaining how to use namespaces in C++/CLI code and then goes on to list some of the major .NET namespaces, together with brief details of their function and content.

You’ve already encountered .NET namespaces in use in C++/CLI code when you’ve used the C++ using keyword, as in the following example:

using namespace System::Collections;

As with traditional C++ namespaces, .NET namespaces provide an additional level of scoping that helps you to organize code and guard against name clashes. Two classes with the same name can be used in an application, provided that they belong to different namespaces. A type name that includes the namespace information is called the fully qualified name, as illustrated in the following examples:

System::Collections::Generic::List  // the List<T> class from
                                    // System::Collections::Generic
System::Threading::Thread           // the Thread class from System::Threading

Namespace names in .NET typically consist of more than one word. In C++/CLI, the components of the name are separated by the scope resolution operator (::). In many other .NET languages such as C# and Visual Basic, the components are separated by using a period (.), so in C#, the preceding examples would be as follows:

System.Collections.Generic.List
System.Threading.Thread

All classes, interfaces, structures, and enumerations that are part of the .NET Framework class library belong to a namespace. Most of the namespaces provided by Microsoft begin with one of two prefixes. Those that start with System have been developed as part of the .NET Framework class library, whereas those beginning with Microsoft have been developed by other product groups within Microsoft.

Namespace names can have any number of components, but there’s no hierarchical relationship implied in names that contain the same root components. The hierarchical nature of namespace names simply gives you a way to organize your classes. So, for example, System::Collections::Generic and System::Collections both contain collections, yet they aren’t necessarily related in any other way.

Note

If you are a Java programmer, keep in mind that although .NET namespaces look very much like Java package names, there’s no relationship between namespace names and directory paths as there is in Java.

There’s no requirement that all the classes belonging to one namespace are defined in the same .dll file or that a single .dll file contains classes from only one namespace.

Using namespaces in C++ applications

C++/CLI applications employ the #using preprocessor directive to import metadata into applications. Remember that metadata is information that describes the types in an assembly, and it includes the fully qualified names of all the types. For example, if the compiler sees a line such as

#using <mscorlib.dll>

it loads the .dll file and reads the metadata for all the types that are defined there. Because mscorlib.dll contains most of the core .NET Framework classes, it imports the metadata for a very large number of types.

Note

You can only use #using to reference assemblies defined in .dll files.

The #using keyword means that you have to know which .dll file holds the class or classes that you want to use. Your typical source for this information is the online help.

Some of the fully qualified names can get rather long. Thus, it’s common to use a traditional using directive to specify namespace names so that you can use unqualified names, as shown here:

// Read the metadata for MSCORLIB
#using <mscorlib.dll>

// Import all the names
using namespace System::Collections::Generic;

// Now you can use List without having to qualify it
List<int> ^pal = gcnew List<int>();

The System namespace

The System namespace, defined in mscorlib.dll, contains a lot of fundamental classes, including the following:

  • Base classes for commonly used value and reference types, plus the base class for arrays

  • Events and event handlers

  • Delegates and interfaces

  • Attributes

  • Exceptions

  • Math

  • Application environment management

  • Garbage collection

  • Local and remote application invocation

  • Data type conversion

You’ve already seen a lot of types from System in earlier chapters, and some of the other classes are rather obscure, so I won’t go through them in detail. There are a few points that are worth mentioning about some of the classes in System; these are covered in the following sections.

Basic types

System implements all the basic types defined by the CTS, and you can find these listed in the following table (which also appears in Chapter 9).

Value type

Description

C++/CLI equivalent type

Byte

An 8-bit unsigned integer

unsigned char

SByte

An 8-bit signed integer

char

Int16

A 16-bit signed integer

short

Int32

A 32-bit signed integer

int or long

Int64

A 64-bit signed integer

__int64 or long long

UInt16

A 16-bit unsigned integer

unsigned short

UInt32

A 32-bit unsigned integer

unsigned int or unsigned long

UInt64

A 64-bit unsigned integer

unsigned __int64 or unsigned long long

Single

A single-precision, 32-bit, floating-point number

float

Double

A double-precision, 64-bit, floating-point number

double

Boolean

A Boolean value

bool

Char

A 16-bit Unicode character

wchar_t

IntPtr

A signed integer whose size depends on the platform

No built-in type

UIntPtr

An unsigned integer whose size depends on the platform

No built-in type

Keep in mind that several of the types—namely the unsigned integer types and SByte—aren’t CLS-compliant, so be wary of using them when you’re writing code that’s going to be used from other .NET languages.

All .NET languages map these types to native types, so C++/CLI maps int to System::Int32, but you can also use the underlying types directly, if you want.

Floating-point types

The Single and Double types implement IEEE-754 floating-point arithmetic. This means that every operation has a defined result, so you never get a divide-by-zero error when performing floating-point math; instead, you get an answer of infinity. The floating-point classes have values to represent positive and negative infinity and “not a number” (often represented as NaN), as well as methods to test for them, as shown in the following example:

double top = 1.0;
double bottom = 0.0;

double result = top/bottom;

if (result == Double::PositiveInfinity)
    Console::WriteLine("+infinity");
else if (result == Double::NegativeInfinity)
    Console::WriteLine("-infinity");
else if (result == Double::NaN)
    Console::WriteLine("Not a number");

The Collections namespaces

Chapter 12, looks at the Collections namespaces, in particular System::Collections::Generic. System::Collections::Generic is implemented in mscorlib.dll, so to use it, you’ll have to include a #using statement, as demonstrated here:

#using <mscorlib.dll>

The following table lists the main classes that you’ll find in the System::Collections::Generic namespace.

Class

Description

Dictionary<K,V>

A collection of key/value pairs

HashSet<T>

A set of objects

LinkedList<T>

A doubly linked list of objects

List<T>

A strongly typed list of objects, retrievable by index

Queue<T>

A FIFO collection of objects

SortedList<K,V>

A collection of key/value pairs sorted on the key

SortedSet<T>

A collection of objects maintained in sorted order

Stack<T>

A LIFO stack

The Collections interfaces

The System::Collections::Generic namespace also defines a series of interfaces that are used to define the behavior of the collection classes. The collection classes themselves implement one or more of these interfaces, and you can use them as the basis for writing your own collection classes. The main interfaces are listed in the following table.

Interface

Description

ICollection<T>

Defines the size, enumerator, and synchronization methods for all collections

IComparer<T>

Defines a method for comparing two objects

IDictionary<K,V>

Implemented by collections that manage key/value pairs, such as Hashtable and ListDictionary

IEnumerable<T>

Defines the GetEnumerator method, which returns an IEnumerator; implemented by almost all collections

IEnumerator<T>

Defines the properties and methods of enumerators

IList<T>

Implemented by classes that define indexed collections of objects

IReadOnlyCollection<T>

Represents a strongly typed, read-only collection of elements

ISet<T>

Implemented by classes that manage sets of objects

The Diagnostics namespace

The System::Diagnostics namespace provides a number of classes with which you can do the following:

  • Trace application execution

  • Interact with the debugger

  • Use the system event log

  • Start system processes

  • Monitor system performance

All the classes in System::Diagnostics are implemented in system.dll.

The IO namespace

The System::IO namespace, defined in mscorlib.dll, provides the classes that implement the .NET input/output (I/O) functionality. The main classes in this namespace are described in the following table.

Class

Description

BinaryReader

Reads .NET primitive types from a byte stream

BinaryWriter

Writes .NET primitive types to a byte stream

Directory

Contains static methods for operating on directories

DirectoryInfo

Represents a path to a directory and contains methods for operating on the directory path

File

Contains static methods for operating on files

FileInfo

Represents a path to a file and contains methods for operating on the file path

FileStream

Reads and writes to files by using streams

FileSystemInfo

The base class for FileInfo and DirectoryInfo

FileSystemWatcher

Watches for changes in the file system and fires events when changes occur

IOException

The exception thrown when I/O errors occur

MemoryStream

Reads and writes streams of bytes to and from memory

Path

Represents directory strings in a platform-independent way

Stream

The abstract base for the stream classes

StreamReader

Reads Unicode characters from a byte stream

StreamWriter

Writes Unicode characters to a byte stream

StringReader

Reads Unicode characters from a string

StringWriter

Writes Unicode characters to a string

TextReader

The base class for StreamReader and StringReader

TextWriter

The base class for StreamWriter and StringWriter

As with all the .NET Framework class library classes, these classes are language-independent. They can be used alongside or in place of the C++ stream classes. Chapter 19, delves deeper into some of the System::IO classes. The System::IO classes are in mscorlib.dll.

The Windows namespaces

The System::Windows prefix identifies 50 namespaces that together provide the functionality of Windows Presentation Foundation (WPF), an advanced user interface (UI) framework for .NET introduced in version 3.0. WPF provides all the tools you need to create modern UIs, including support for forms-based applications, 2D and 3D graphics, typography and printing, run-time animation, and comprehensive support for playing media.

Note

In earlier versions of the .NET Framework, you built UIs by using a technology called Windows Forms, which was heavily influenced by Visual Basic.

One key feature of WPF is its use of XAML, an XML markup language, to define user interfaces. This makes it possible to separate the UI from the code, which allows teams to use design tools such as Microsoft Expression Blend in addition to coding tools such as Microsoft Visual Studio.

The Net namespaces

Networking support is provided by a number of namespaces in the System::Net family. System::Net itself provides an interface to many of the protocols commonly used today, such as manipulating IP addresses, making DNS lookups, talking to HTTP and FTP servers, managing cookies, and authentication.

System::Net::Sockets provides an implementation of the Berkeley Sockets protocol and provides a .NET wrapper around the Windows WinSock API, whereas System::Net::WebSockets provides a managed implementation of the WebSocket interface.

The ServiceModel namespaces

The System::ServiceModel namespaces (over 30 of them) together implement Windows Communication Foundation (WCF), a technology introduced in .NET 3.0 for creating distributed, service-oriented applications.

With WCF, you can build applications out of components hosted in other processes, and even on other computers. This has long been possible, but the technologies used were very different, depending on where your components were located (same process, different process on the same computer, or different process on another computer) and the communication mechanism you wanted to use (TCP/IP, HTTP, messaging).

WCF provides an integrated framework for creating, deploying, and managing distributed components and their clients. Chapter 19 shows you how to write a web service by using WCF.

The Xml namespaces

XML is heavily used throughout the .NET Framework, and several namespaces provide support for creating and manipulating XML, including the following:

  • System::Xml Provides the basic classes needed for processing XML

  • System::Xml::Linq Makes it possible to use Language-Integrated Query (LINQ) to work with XML data

  • System::Xml::Schema Provides support for XML schemas

  • System::Xml::Serialization Gives you the ability to serialize .NET objects to and from XML

  • System::Xml::XPath Contains the XPath parser and evaluation engine

  • System::Xml::Xsl Contains the Extensible Stylesheet Language (XSL) processor

Using these classes, it’s possible to perform all the manipulation of XML that you’ll ever need to do. These classes make the .NET Framework one of the most productive environments for XML programming. You can find the XML classes in System.Xml.dll, with the LINQ classes in System.Xml.Linq.dll.

The Data namespaces

The System::Data namespaces hold the classes that implement ADO.NET, a framework with which you can build components to manage data from a number of data sources. Data from different data sources is provided by data providers, five of which are shipped with the .NET Framework.

  • System.Data.OleDb Object Linking and Embedding Database (OLE DB)–based technology that makes it possible to use many different kinds of data sources—such as relational database tables, Microsoft Excel spreadsheets, and even text files—as if they were databases.

  • System.Data.Odbc The ODBC provider gives access to Open Database Connectivity (ODBC) data sources, including Microsoft Access databases.

  • System.Data.SqlClient This provider is optimized for use with Microsoft SQL Server.

  • System.Data.OracleClient The provider for Oracle makes it possible to work with Oracle databases from .NET code.

  • System.Data.EntityClient Entity Framework (EF) is an object-relational mapping framework that can be used from ADO.NET, making it possible to map managed objects to a backing database automatically.

The most important class in the System::Data namespace itself is DataSet, which represents an in-memory cache of data retrieved from a data source. A DataSet consists of one or more DataTable objects, and these in turn consist of a collection of DataColumn and DataRow objects. You can use DataSets to work in disconnected mode. This means retrieve data from a database into a DataSet, disconnect from the database server and work with the data locally, and then update the database from the DataSet later.

The Web namespaces

Because one of the main reasons for introducing the .NET Framework was to make it easier to build web applications, it’s perhaps no surprise that the .NET Framework contains a number of namespaces related to web programming. These are all related to Microsoft ASP.NET, the latest version of Microsoft Active Server Pages technology that is optimized to work in the .NET environment.

The most significant of the Web namespaces are listed here:

  • System::Web This provides the basic functionality for browser-to-server communication over HTTP, including the HttpRequest and HttpResponse classes that enable an ASP.NET page to exchange data with the client by using HTTP.

  • System::Web::Mail This makes it possible for you to prepare and send email attachments by using the Simple Mail Transfer Protocol (SMTP) service that is built in to the Windows operating system.

  • System::Web::Security This provides classes that implement security in ASP.NET.

  • System::Web::Services This provides the classes with which you can build web services.

  • System::Web::UI This contains all the classes with which you can build server-side controls.

The features provided by two of these namespaces merit particular mention. A web service is a programmable entity living on a web server that can be accessed by using standard Internet protocols. What this means in practice is that you can expose a function on a web server that others can call. Communication between client and server uses standard protocols such as HTTP, and data is usually passed to and from the web service in XML format by using Simple Object Access Protocol (SOAP). The use of XML over HTTP makes it possible to access web services easily from clients written in just about any programming language on any platform. It’s also possible to find out what services a web server supports, and it’s very easy in Visual Studio 2012 to write clients that make use of web services.

With the System::Web::UI namespaces, you can build server-side controls. You program these as if they were normal controls, but their code executes on the server. The System::Web::UI::HtmlControls namespace contains classes that represent HTML server controls that map directly to standard HTML elements such as buttons and forms. System::Web::UI::WebControls is more abstract, and you can use it to program server-side controls that might not map directly to HTML.

Quick reference

To

Do this

Use data structures such as dynamic arrays, lists, and hash tables.

Use the classes in the System::Collections::Generic namespace.

Create a form-based application.

Use the classes in System::Windows::Forms, and derive a class from System::Windows::Forms::Form.

Work with XML.

Look at the classes in the System::Xml namespace.

Trace application execution, interact with the event log, or monitor system performance.

Use the classes in the System::Diagnostics namespace.

Work with databases by using ADO.NET.

Look at the System::Data namespaces.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.62.122