BUY THIS BOOK
Add to Cart

Print Book $39.99


Add to Cart

Print+PDF $51.99

Add to Cart

PDF $31.99

Safari Books Online

What is this?

Add to UK Cart

Print Book £20.95

What is this?

Looking to Reprint or License this content?


.NET Framework Essentials
.NET Framework Essentials, Third Edition By Thuan L. Thai, Hoang Lam
August 2003
Pages: 380

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: .NET Overview
The .NET Framework is a development framework that provides a new programming interface to Windows services and APIs, and integrates a number of technologies that emerged from Microsoft during the late 1990s. Microsoft announced the .NET initiative in July 2000. In April 2003, Version 1.1 of the integral .NET Framework was released. This book describes this updated version of the .NET Framework.
The .NET platform consists of four separate product groups:
Development tools and libraries
A set of languages, including C#, J#, and VB.NET; a set of development tools, including Visual Studio .NET; a comprehensive class library for building web services and web and Windows applications; as well as the Common Language Runtime (CLR). These components collectively form the largest part of the .NET Framework.
Web services
An offering of commercial web services, specifically the .NET Services initiative; for a fee, developers can use these services in building applications that require them.
Specialized servers
A set of .NET-enabled enterprise servers, including SQL Server, Exchange Server, BizTalk Server, and so on. These provide specialized functionality for relational data storage, email, and B2B commerce. Future versions of these products will increasingly support the .NET Framework.
Devices
New .NET-enabled, non-PC devices, from cell phones to game boxes.
While the main strategy of .NET is to enable software as a service, .NET is much more than that. In addition to embracing the Web, Microsoft .NET acknowledges and responds to the following trends within the software industry:
Distributed computing
Simplifies the development of robust client/server and multi-tier (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Behind Microsoft .NET
While the main strategy of .NET is to enable software as a service, .NET is much more than that. In addition to embracing the Web, Microsoft .NET acknowledges and responds to the following trends within the software industry:
Distributed computing
Simplifies the development of robust client/server and multi-tier (n-tier) applications. Traditional distributed technologies require high vendor-affinity and are unable to interoperate with the Web. Microsoft .NET provides remoting and web services architectures that exploit open Internet standards, including the Hypertext Transfer Protocol (HTTP), Extensible Markup Language (XML), and Simple Object Access Protocol (SOAP) and WSOL.
Componentization
Simplifies the integration of software components developed by different vendors and supports development of distributed applications. The Component Object Model (COM) has brought reality to software plug-and-play, but COM component development and deployment are too complex. Microsoft .NET provides a simpler way to build and deploy components.
Enterprise services
Allow the development of scalable enterprise applications without writing code to manage transactions, security, or pooling. Microsoft .NET continues to support COM and component services, since these services greatly reduce the development time and effort required to build large-scale applications.
Web paradigm shifts
Over the past decade, web application development has shifted from connectivity (TCP/IP), to presentation (HTML), to programmability (XML and SOAP). A key goal of Microsoft .NET is to enable the sharing of functionality across the Web among different platforms, devices, and programming languages.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The .NET Platform
The Microsoft .NET platform consists of five main components, as shown in Figure 1-1. At the lowest layer lies the operating system (OS), which can be one of a variety of Windows platforms, including Windows XP, Windows 2000, Windows Server 2003, Windows ME, and Windows CE. As part of the .NET strategy, Microsoft has promised to deliver more .NET device software to facilitate a new generation of smart devices.
Figure 1-1: The Microsoft .NET platform
On top of the operating system is a collection of specialized server products that shortens the time required to develop large-scale business systems. These server products include Application Center, BizTalk Server, Commerce Server, Exchange Server, Host Integration Server, Internet Security and Acceleration Server, and SQL Server.
Since web services are highly reusable across the Web, Microsoft provides a number of building-block services (officially called .NET Services) that applications developers can use, for a fee. Two examples of .NET Services that Microsoft offers include .NET Passport and .NET Alerts. .NET Passport allows you to use a single username and password at all web sites that support Passport authentication. .NET Alerts allow .NET Alert providers, such as a business, to alert their consumers with important or up-to-the-minute information. Microsoft plans to add newer services, such as calendar, directory, and search services. Third-party vendors are also creating new web services of their own.
The top layer of the .NET architecture is a development tool called Visual Studio .NET (VS.NET), which makes possible the rapid development of web services and other applications. A successor to Microsoft Visual Studio 6.0, VS.NET is an Integrated Development Environment (IDE) that supports four different languages and features such as cross-language debugging and the XML Schema Editor.
And at the center of .NET is the Microsoft .NET Framework—the main focus of this book. The .NET Framework is a development and runtime infrastructure that changes the development of business applications on the Windows platform. The .NET Framework includes the CLR and a common framework of classes that can be used by all .NET languages.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
.NET Framework Design Goals
The Microsoft .NET Framework embodies design goals that are both practical and ambitious. In this section, we discuss the main design goals of the Microsoft .NET Framework, including support for components, language integration, application interoperation across the Web, simplified development and deployment, improved reliability, and greater security.
Prior to the introduction of COM technology, developers had no standard way to integrate binary libraries without referring to or altering their source code. With the advent of COM, programmers were able to integrate binary components into their applications, similar to the way we can plug-and-play hardware components into our desktop PCs. Although COM was great, the grungy details of COM gave developers and administrators many headaches.
Although COM permits you to integrate binary components developed using any language, it does require you to obey the COM identity, lifetime, and binary layout rules. You must also write the plumbing code that is required to create a COM component, such as DllGetClassObject, CoRegisterClassObject, and others.
Realizing that these requirements result in frequent rewrites of similar code, .NET sets out to remove them. In the .NET world, all classes are ready to be reused at the binary level. You don't have to write extra plumbing code to support componentization in the .NET Framework. You simply write a .NET class, which then becomes a part of an assembly (to be discussed in Chapter 2) that inherently supports plug-and-play.
In addition to providing a framework to make development easier, .NET removes the pain of developing COM components. Specifically, .NET removes the use of the registry for component registration and eliminates the requirements for extraneous plumbing code found in all COM components, including code to support IUnknown, class factories, component lifetime, registration, dynamic binding, and others.
"Component" is a nasty word because one person may use it to refer to an object and another may use it to refer to a compiled binary module. To be consistent, this book uses the term "COM component" (or simply "component") to refer to a binary module, such as a DLL or an EXE.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
.NET Framework
Now that you are familiar with the major goals of the .NET Framework, let's briefly examine its architecture. As you can see in Figure 1-2, the .NET Framework sits on top of the operating system, which can be a few different flavors of Windows and consists of a number of components (each of these components is discussed in greater detail starting with Chapter 4, as described in the Preface). .NET is essentially a system application that runs on Windows.
Figure 1-2: The .NET Framework
The most important component of the framework is the CLR. If you are a Java programmer, think of the CLR as the .NET equivalent of the Java Virtual Machine (JVM). If you don't know Java, think of the CLR as the heart and soul of the .NET architecture. At a high level, the CLR activates objects, performs security checks on them, lays them out in memory, executes them, and garbage-collects them.
Conceptually, the CLR and the JVM are similar in that they are both runtime infrastructures that abstract the underlying platform differences. However, while the JVM officially supports only the Java language, the CLR supports any language that can be represented in its Common Intermediate Language (CIL). The JVM executes bytecode, so it can, in principle, support many languages, too. Unlike Java's bytecode, though, CIL is never interpreted. Another conceptual difference between the two infrastructures is that Java code runs on any platform with a JVM, whereas .NET code runs only on platforms that support the CLR. In April, 2003, the International Organization for Standardization and the International Electrotechnical Committee (ISO/IEC) recognized a functional subset of the CLR, known as the Common Language Interface (CLI), as an international standard. This development, initiated by Microsoft and developed by ECMA International, a European standards organization, opens the way for third parties to implement their own versions of the CLR on other platforms, such as Linux or Mac OS X. For information on third-party and open source projects working to implement the ISO/IEC CLI and C# specifications, see Appendix A.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: The Common Language Runtime
The most important component of the .NET Framework is the Common Language Runtime (CLR). The CLR manages and executes code written in .NET languages and is the basis of the .NET architecture, similar to the Java Virtual Machine. The CLR activates objects, performs security checks on them, lays them out in memory, executes them, and garbage-collects them.
In this chapter, we describe the CLR environment, executables (with examples in several languages), metadata, assemblies, manifests, the CTS, and the CLS.
The CLR is the underlying .NET infrastructure. Its facilities cover all the goals that we spelled out in Chapter 1. Unlike software libraries such as MFC or ATL, the CLR is built from a clean slate. The CLR manages the execution of code in the .NET Framework.
An assembly is the basic unit of deployment and versioning, consisting of a manifest, a set of one or more modules, and an optional set of resources.
Figure 2-1 shows the two portions of the .NET environment, with the bottom portion representing the CLR and the top portion representing the CLR executables or Portable Executable (PE) files, which are .NET assemblies or units of deployment. The CLR is the runtime engine that loads required classes, performs just-in-time compilation on needed methods, enforces security checks, and accomplishes a bunch of other runtime functionalities. The CLR executables shown in Figure 2-1 are either EXE or DLL files that consist mostly of metadata and code.
Figure 2-1: The CLR environment
Microsoft .NET executables are different from typical Windows executables in that they carry not only code and data, but also metadata (see Section 2.3 and Section 2.5 later in this chapter). In this section, we start off with the code for several .NET applications, and discuss the .NET PE format.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
CLR Environment
The CLR is the underlying .NET infrastructure. Its facilities cover all the goals that we spelled out in Chapter 1. Unlike software libraries such as MFC or ATL, the CLR is built from a clean slate. The CLR manages the execution of code in the .NET Framework.
An assembly is the basic unit of deployment and versioning, consisting of a manifest, a set of one or more modules, and an optional set of resources.
Figure 2-1 shows the two portions of the .NET environment, with the bottom portion representing the CLR and the top portion representing the CLR executables or Portable Executable (PE) files, which are .NET assemblies or units of deployment. The CLR is the runtime engine that loads required classes, performs just-in-time compilation on needed methods, enforces security checks, and accomplishes a bunch of other runtime functionalities. The CLR executables shown in Figure 2-1 are either EXE or DLL files that consist mostly of metadata and code.
Figure 2-1: The CLR environment
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
CLR Executables
Microsoft .NET executables are different from typical Windows executables in that they carry not only code and data, but also metadata (see Section 2.3 and Section 2.5 later in this chapter). In this section, we start off with the code for several .NET applications, and discuss the .NET PE format.
Let's start off by examining a simple Hello, World application written in Managed C++, a Microsoft .NET extension to the C++ language. Managed C++ includes a number of new CLR-specific keywords that permit C++ programs to take advantage of CLR features, including garbage collection. Here's the Managed C++ version of our program:
               #using <mscorlib.dll>

using namespace System;

void main(  )
{
  Console::WriteLine(L"C++ Hello, World!");
}
As you can see, this is a simple C++ program with an additional directive, #using (shown in bold). If you have worked with the Microsoft Visual C++ compiler support features for COM, you may be familiar with the #import directive. While #import reverse-engineers type information to generate wrapper classes for COM interfaces, #using makes all types accessible from the specified DLL, similar to a #include directive in C or C++. However, unlike #include, which imports C or C++ types, #using imports types for any .NET assembly, written in any .NET language.
The one and only statement within the main( ) method is self-explanatory—it means that we are invoking a static or class-level method, WriteLine( ), on the Console class. The L that prefixes the literal string tells the C++ compiler to convert the literal into a Unicode string. You may have already guessed that the Console class is a type hosted by mscorlib.dll, and the WriteLine( ) method takes one string parameter.
One thing that you should also notice is that this code signals to the compiler that we're using the types in the System namespace, as indicated by the using
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Metadata
Metadata is machine-readable information about a resource, or "data about data." Such information might include details on content, format, size, or other characteristics of a data source. In .NET, metadata includes type definitions, version information, external assembly references, and other standardized information.
In order for two systems, components, or objects to interoperate with one another, at least one must know something about the other. In COM, this "something" is an interface specification, which is implemented by a component provider and used by its consumers. The interface specification contains method prototypes with full signatures, including the type definitions for all parameters and return types.
Only C/C++ developers were able to readily modify or use Interface Definition Language (IDL) type definitions—not so for VB or other developers, and more importantly, not for tools or middleware. So Microsoft invented something other than IDL that everyone could use, called a type library. In COM, type libraries allow a development environment or tool to read, reverse engineer, and create wrapper classes that are most appropriate and convenient for the target developer. Type libraries also allow runtime engines, such as the VB, COM, MTS, or COM+ runtime, to inspect types at runtime and provide the necessary plumbing or intermediary support for applications to use them. For example, type libraries support dynamic invocation and allow the COM runtime to provide universal marshaling for cross-context invocations.
Type libraries are extremely rich in COM, but many developers criticize them for their lack of standardization. The .NET team invented a new mechanism for capturing type information. Instead of using the term "type library," we call such type information metadata in .NET.
Just as type libraries are C++ header files on steroids, metadata is a type library on steroids. In .NET, metadata is a common mechanism or dialect that the .NET runtime, compilers, and tools can all use. Microsoft .NET uses metadata to describe all types that are used and exposed by a particular .NET assembly. In this sense, metadata describes an assembly in detail, including descriptions of its identity (a combination of an assembly name, version, culture, and public key), the types that it references, the types that it exports, and the security requirements for execution. Much richer than a type library, metadata includes descriptions of an assembly and modules, classes, interfaces, methods, properties, fields, events, global methods, and so forth.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Assemblies and Manifests
As we just saw, types must expose their metadata to allow tools and programs to access them and benefit from their services. Metadata for types alone is not enough. To simplify software plug-and-play and configuration or installation of the component or software, we also need metadata about the component that hosts the types. Now we'll talk about .NET assemblies (deployable units) and manifests (the metadata that describes the assemblies).
During the COM era, Microsoft documentation inconsistently used the term component to mean a COM class or a COM module (DLLs or EXEs), forcing readers or developers to consider the context of the term each time they encountered it. In .NET, Microsoft has addressed this confusion by introducing a new concept, assembly, which is a software component that supports plug-and-play, much like a hardware component. Theoretically, a .NET assembly is approximately equivalent to a compiled COM module. In practice, an assembly can contain or refer to a number of types and physical files (including bitmap files, .NET PE files, and so forth) that are needed at runtime for successful execution. In addition to hosting IL code, an assembly is a basic unit of versioning, deployment, security management, side-by-side execution, sharing, and reuse, as we discuss next.
To review: an assembly is a logical DLL or EXE, and a manifest is a detailed description (metadata) of an assembly, including its version, what other assemblies it uses, and so on.
Type uniqueness is important in RPC, COM, and .NET. Given the vast number of GUIDs in COM (application, library, class, and interface identifiers), development and deployment can be tedious because you must use these magic numbers in your code and elsewhere all the time. In .NET, you refer to a specific type by its readable name and its namespace. Since a readable name and its namespace are not enough to be globally unique, .NET guarantees uniqueness by using unique public/private key pairs. All assemblies that are shared (called
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Intermediate Language (IL)
In software engineering, the concept of abstraction is extremely important. We often use abstraction to hide the complexity of system or application services, providing instead a simple interface to the consumer. As long as we can keep the interface the same, we can change the hideous internals, and different consumers can use the same interface.
In language advances, scientists introduced different incarnations of language-abstraction layers, such as p-code and bytecode. Produced by the Pascal-P compiler, p-code is an intermediate language that supports procedural programming. Generated by Java compilers, bytecode is an intermediate language that supports object-oriented programming. Bytecode is a language abstraction that allows Java code to run on different operating platforms, as long as the platforms have a Java Virtual Machine (JVM) to execute bytecode.
Microsoft calls its own language-abstraction layer the Microsoft Intermediate Language (MSIL) or IL, for short. IL is an implementation of the Common Intermediate Language (CIL), a key element of the EMCA CLI specification. Similar to bytecode, IL supports all object-oriented features, including data abstraction, inheritance, polymorphism, and useful concepts such as exceptions and events. In addition to these features, IL supports other concepts, such as properties, fields, and enumeration. Any .NET language may be converted into IL, so .NET supports multiple languages and multiple platforms, as long as the target platforms have a CLR.
Shipped with the .NET SDK, Partition III CIL.doc describes the important IL instructions that language compilers should use. In addition to this specification, the .NET SDK includes another important document, Partition II Metadata.doc. Both of these documents are intended for developers who write compilers and tools, but you should read them to further understand how IL fits into .NET. Although you can develop a valid .NET assembly using the supported IL instructions and features, you'll find IL to be very tedious because the instructions are a bit cryptic. However, should you decide to write pure IL code, you could use the IL Assembler (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The CTS and CLS
Having seen the importance of metadata and IL, let's examine the CTS and the CLS. Both the CTS and the CLS ensure language compatibility, interoperability, and integration.
Because .NET treats all languages as equal, a class written in C# should be equivalent to a class written in VB.NET, and an interface defined in Managed C++ should be exactly the same as one that is specified in Managed COBOL. Languages must agree on the meanings of these concepts before they can integrate with one another. In order to make language integration a reality, Microsoft has specified a common type system by which every .NET language must abide. In this section, we outline the common types that have the same conceptual semantics in every .NET language. Microsoft .NET supports a rich set of types, but we limit our discussion to the important ones, including value types, reference types, classes, interfaces, and delegates.

Section 2.6.1.1: Value types

In general, the CLR supports two different types: value types and reference types. Value types represent values allocated on the stack. They cannot be null and must always contain some data. When value types are passed into a function, they are passed by value, meaning that a copy of the value is made prior to function execution. This implies that the original value won't change, no matter what happens to the copy during the function call. Since intrinsic types are small in size and don't consume much memory, the resource cost of making a copy is negligible and outweighs the performance drawbacks of object management and garbage collection. Value types include primitives, structures, and enumerations; examples are shown in the following C# code listing:
int i;                     // Primitive
struct Point { int x, y; } // Structure
enum State { Off, On }     // Enumeration
You can also create a value type by deriving a class from System.ValueType. One thing to note is that a value type is
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
CLR Execution
Now that you understand the elements of a .NET executable, let's talk about the services that the CLR provides to support management and execution of .NET assemblies. There are many fascinating components in the CLR, but for brevity, we will limit our discussions to just the major components, as shown in Figure 2-4.
Figure 2-4: Major CLR components: the Virtual Execution System (VES)
The major components of the CLR include the class loader, verifier, JIT compilers, and other execution support, such as code management, security management, garbage collection, exception management, debug management, marshaling management, thread management, and so on. As you can see from Figure 2-4, your .NET PE files lay on top of the CLR and execute within the CLR's Virtual Execution System (VES), which hosts the major components of the runtime. Your .NET PE files will have to go through the class loader, the type verifier, the JIT compilers, and other execution support components before they will execute.
When you run a standard Windows application, the OS loader loads it before it can execute. At the time of this writing, the default loaders in the existing Windows operating systems, such as Windows 98, Windows Me, Windows 2000, and so forth, recognize only the standard Windows PE files. As a result, Microsoft has provided an updated OS loader for each of these operating systems that support the .NET runtime. The updated OS loaders know the .NET PE file format and can handle the file appropriately.
When you run a .NET application on one of these systems that have an updated OS loader, the OS loader recognizes the .NET application and thus passes control to the CLR. The CLR then finds the entry point, which is typically Main( ), and executes it to jump-start the application. But before Main( ) can execute, the class loader must find the class that exposes
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
As you can see from this chapter, the .NET architecture strives to support language integration and componentization in every way that makes sense. Thanks to metadata, programming becomes much easier because you no longer have to worry about the registry for component deployment and other kinks (such as CoCreateInstanceEx, CLSIDs, IIDs, IUnknown, IDL, and so forth) in order to support componentization. Thanks to the CTS, CLS, metadata, and IL, you now have real language integration. Microsoft has shipped a CLR for several flavors of Windows, and has released their shared-source implementation of the CLR that will run on FreeBSD and will no doubt be portable to other Unix-like systems. Non-Microsoft implementations of the CLR have also appeared, including DotGNU Portable.NET (for more information, see http://www.southern-storm.com.au/portable_net.html) and Mono (see http://www.go-mono.com). .NET is thus a multilanguage and multiplatform architecture.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: .NET Programming
Now that you know what .NET is all about, let's talk about programming for the .NET environment. This chapter presents the common programming model that .NET provides, the core languages and features that .NET supports, and language integration—how you can take advantage of object-oriented features even across different languages that target the CLR.
Without the .NET Framework, programmers must choose from a wealth of APIs or libraries that support system services. For example, if you want to write GUI applications on Windows, you have a slew of options from which to choose, including the Win32 API, MFC, ATL, VB, and so on. Once you've chosen the library, you have to learn how to use the structures, classes, functions, interfaces, and so forth that the library provides. Unfortunately, this knowledge doesn't transfer directly into a different environment. For instance, there's a big difference between the code to manage IO in MFC and the code to manage IO in VB.
One of the goals of the .NET Framework is to bring commonality to application development by providing a framework of common classes to developers who are using compilers that generate IL. This set of classes, known as the Base Class Library (BCL), is extremely helpful: if you know how to take advantage of IO functionality in .NET using your favorite language, you can easily port that code to another language. This is possible because the namespaces, classes, methods, and so forth are equally accessible in all languages. For example, you can output a line of text to the console the same way across all .NET languages by using the WriteLine( ) method of the Console object, as we have seen elsewhere in this book. This consistent framework requires less development training and enables higher programmer productivity.
Since a full discussion of the entire set of classes in the .NET BCL is beyond the scope of this book (see O'Reilly's In a Nutshell .NET series), we talk about the System.Object class and present the major namespaces in the .NET Framework, opening the doors for you to step into this world.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Common Programming Model
Without the .NET Framework, programmers must choose from a wealth of APIs or libraries that support system services. For example, if you want to write GUI applications on Windows, you have a slew of options from which to choose, including the Win32 API, MFC, ATL, VB, and so on. Once you've chosen the library, you have to learn how to use the structures, classes, functions, interfaces, and so forth that the library provides. Unfortunately, this knowledge doesn't transfer directly into a different environment. For instance, there's a big difference between the code to manage IO in MFC and the code to manage IO in VB.
One of the goals of the .NET Framework is to bring commonality to application development by providing a framework of common classes to developers who are using compilers that generate IL. This set of classes, known as the Base Class Library (BCL), is extremely helpful: if you know how to take advantage of IO functionality in .NET using your favorite language, you can easily port that code to another language. This is possible because the namespaces, classes, methods, and so forth are equally accessible in all languages. For example, you can output a line of text to the console the same way across all .NET languages by using the WriteLine( ) method of the Console object, as we have seen elsewhere in this book. This consistent framework requires less development training and enables higher programmer productivity.
Since a full discussion of the entire set of classes in the .NET BCL is beyond the scope of this book (see O'Reilly's In a Nutshell .NET series), we talk about the System.Object class and present the major namespaces in the .NET Framework, opening the doors for you to step into this world.
Every type in .NET is an object, meaning that it must derive directly or indirectly from the Object class. If you don't specify a base class when you define a class, the compiler will inject this requirement into the IL code. The Object class supports a commonality that all .NET classes inherit and, thus, automatically provide to their consumers. The Object class exposes the public methods listed in Table 3-1, which you can invoke on any given .NET object at runtime.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Core Features and Languages
Since one of .NET's goals is to support a common paradigm for application programming, it must specify and utilize programming concepts consistently. In this section, we will examine four core Microsoft .NET languages, including Managed C++, VB.NET, C#, and J#, and several core programming concepts that all .NET languages support, including:
Namespace
Mitigates name collisions.
Interface
Specifies the methods and properties that must be implemented by objects that expose the interface.
Encapsulation
In object-oriented languages, allows a class to combine all its data and behavior.
Inheritance
Allows a class to inherit from a parent class so that it can reuse rich functionality that the parent class has implemented, thus reducing development effort and programming errors.
Polymorphism
Permits developers to specify or implement behaviors in a base class that can be overridden by a derived class. This is a very powerful feature because it allows developers to select the correct behavior based on the referenced runtime object.
Exception handling
Allows us to write easier-to-understand code because it allows us to capture all errors in a common, understandable pattern—totally opposite to that of nine levels of nested conditional blocks.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Language Integration
In the previous section, we saw that you can take advantage of .NET object-oriented concepts in any .NET language. In this section, we show that you can take advantage of language integration—the ability to derive a class from a base that is specified in a totally different language; to catch exceptions thrown by code written in a different language; or to take advantage of polymorphism across different languages, and so forth.
Before we discuss the examples in this section, let's first understand what we want to accomplish (see Figure 3-1). We will first use Managed C++ to develop a Vehicle class that is an abstract base class. The Vehicle class exposes three polymorphic methods, including TurnLeft( ), TurnRight( ), and ApplyBrakes( ). We will then use VB.NET to develop a Car class that derives from Vehicle and overrides these three virtual methods. In addition, we will use C# to develop the Plane class that derives from Vehicle and overrides these three virtual methods.
Figure 3-1: Polymorphism across languages
In the upcoming code example, we can tell a Vehicle to TurnLeft( ) or TurnRight( ), but what turns left or right depends on the target object, whether a Car or a Plane. Unlike the examples in the previous section, the examples here illustrate that we can inherit classes and call virtual functions from ones that are defined in another language. In addition, we will demonstrate in our test program that exception handling works across different languages.
Let's use Managed C++ to develop the Vehicle class, which is an abstract base class because ApplyBrakes( ) is a pure virtual function. Vehicle implements the ISteering interface to support turning left and turning right. Since the ApplyBrakes( ) function is a pure virtual function, any concrete derivative of Vehicle must implement this method:
#using <mscorlib.dll>
using namespace System;

public _  _gc _  _interface ISteering
{
  void TurnLeft(  );
  void TurnRight(  );
};

public _  _gc class Vehicle : public ISteering  
{
  public:

    virtual void TurnLeft(  )
    {
      Console::WriteLine("Vehicle turns left."); 
    }

    virtual void TurnRight(  )
    {
      Console::WriteLine("Vehicle turns right."); 
    }

    virtual void ApplyBrakes(  ) = 0; 
};
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
We started this chapter by telling you that .NET provides a common programming model, which reduces the learning curve and increases productivity. Once you've learned how to do something using the classes in the .NET Framework, this knowledge will transfer to any .NET language. We then illustrated that we could write the same type of code, supporting major .NET features, in any given language that targets the CLR. Finally, we proved to you that .NET indeed supports language integration, which was never possible using Microsoft platforms and tools, prior to .NET.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: Working with .NET Components
Having seen the language-integration examples in the previous chapter, you now know that all .NET assemblies are essentially binary components. You can treat each .NET assembly as a component that you can plug into another component or application, without the need for source code, since all the metadata for the component is stored inside the .NET assembly. While you have to write a ton of plumbing code to build a component in COM, creating a component in .NET involves no extra work, as all .NET assemblies are components by nature.
In this chapter, we examine the more advanced topics, including component deployment, distributed components, and enterprise services, such as transaction management, object pooling, role-based security, and message queuing.
For a simple program like hello.exe that we built in Chapter 2, deployment is easy: copy the assembly into a directory, and it's ready to run. When you want to uninstall it, remove the file from the directory. However, when you want to share components with other applications, you've got to do some work.
In COM, you must store activation and marshaling information in the registry for components to interoperate; as a result, any COM developer can discuss at length the pain and suffering inherent in COM and the system registry. In .NET, the system registry is no longer necessary for component integration.
In the .NET environment, components can be private, meaning that they are unpublished and used by known clients, or shared, meaning that they are published and can be used by any clients. This section discusses several options for deploying private and shared components.
If you have private components that are used only by specific clients, you have two deployment options. You can store the private components and the clients that use these components in the same directory, or you can store the components in a component-specific directory that the client can access. Since these clients use the exact private components that they referenced at build time, the CLR doesn't support version checking or enforce version policies on private components.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Deployment Options
For a simple program like hello.exe that we built in Chapter 2, deployment is easy: copy the assembly into a directory, and it's ready to run. When you want to uninstall it, remove the file from the directory. However, when you want to share components with other applications, you've got to do some work.
In COM, you must store activation and marshaling information in the registry for components to interoperate; as a result, any COM developer can discuss at length the pain and suffering inherent in COM and the system registry. In .NET, the system registry is no longer necessary for component integration.
In the .NET environment, components can be private, meaning that they are unpublished and used by known clients, or shared, meaning that they are published and can be used by any clients. This section discusses several options for deploying private and shared components.
If you have private components that are used only by specific clients, you have two deployment options. You can store the private components and the clients that use these components in the same directory, or you can store the components in a component-specific directory that the client can access. Since these clients use the exact private components that they referenced at build time, the CLR doesn't support version checking or enforce version policies on private components.
To install your applications in either of these cases, perform a simple xcopy of your application files from the source installation directory to the destination directory. When you want to remove the application, remove these directories. You don't have to write code to store information into the registry, so there's no worrying about whether you've missed inserting a registry setting for correct application execution. In addition, because nothing is stored in the registry, you don't have to worry about registry residues.

Section 4.1.1.1: One-directory deployment

Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Distributed Components
A component technology should support distributed computing, allowing you to activate and invoke remote services, as well as services in another application domain. Distributed COM, or DCOM, is the wire protocol that provides support for distributed computing using COM. Although DCOM is fine for distributed computing, it is inappropriate for global cyberspace because it doesn't work well in the face of firewalls and NAT software. Some other shortcomings of DCOM are expensive lifecycle management, protocol negotiation, and binary formats.
To eliminate or at least mitigate these shortcomings, .NET provides a host of different distributed support. The Remoting API in .NET allows you to use a host of channels, such as TCP and HTTP (which uses SOAP by default), for distributed computing. It even permits you to plug in your own custom channels, should you require this functionality. Best of all, since the framework is totally object-oriented, distributed computing in .NET couldn't be easier. To show you how simple it is to write a distributed application in .NET, let's look at an example using sockets, otherwise known as the TCP channel in .NET.
In this example, we'll write a distributed Hello application, which outputs a line of text to the console whenever a client invokes its exposed method, SayHello( ). Since we're using the TCP channel, we'll tell the compiler that we need the definitions in the System.Runtime.Remoting and System.Runtime.Remoting.Channels.Tcp namespaces.
Note that this class, CoHello, derives from MarshalByRefObject.
This is the key to distributed computing in .NET because it gives this object a distributed identity, allowing the object to be referenced across application domains, or even process and machine boundaries. A marshal-by-reference object requires a proxy to be set up on the client side and a stub to be set up on the server side, but since both of these are automatically provided by the infrastructure, you don't have to do any extra work. Your job is to derive from MarshalByRefObject to get all the support for distributed computing:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
COM+ Services in .NET
COM programming requires lots of housekeeping and infrastructure-level code to build large-scale, enterprise applications. To make it easier to develop and deploy transactional and scalable COM applications, Microsoft released Microsoft Transaction Server (MTS). MTS allows you to share resources, thereby increasing the scalability of an application. COM+ Services were the natural evolution of MTS. While MTS was just another library on top of COM, COM+ Services were subsumed into the COM library, thus combining both COM and MTS into a single runtime.
COM+ Services have been very valuable to the development shops using the COM model to build applications that take advantage of transactions, object pooling, role-based security, etc. If you develop enterprise .NET applications, the COM+ Services in .NET are a must.
In the following examples, rather than feeding you more principles, we'll show you examples for using major COM+ Services in .NET, including examples on transactional programming, object pooling, and role-based security. But before you see these examples, let's talk about the key element—attributes—that enables the use of these services in .NET.
Attributes are the key element that helps you write less code and allows an infrastructure to automatically inject the necessary code for you at runtime. If you've used IDL (Interface Definition Language) before, you have seen the in or out attributes, as in the following example:
HRESULT SetAge([in] short age);
HRESULT GetAge([out] short *age);
IDL allows you to add these attributes so that the marshaler will know how to optimize the use of the network. Here, the in attribute tells the marshaler to send the contents from the client to the server, and the out attribute tells the marshaler to send the contents from the server to the client. In the SetAge( ) method, passing age from the server to the client will just waste bandwidth. Similarly, there's no need to pass
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Message Queuing
In addition to providing support for COM+ Services, .NET also supports message queuing. If you've used Microsoft Message Queuing (MSMQ) services before, you'll note that the basic programming model is the same but the classes in the System.Messaging namespace make it extremely easy to develop message-queuing applications. The System.Messaging namespace provides support for basic functionality, such as connecting to a queue, opening a queue, sending messages to a queue, receiving messages from a queue, and peeking for messages on the queue. To demonstrate how easy it is to use the classes in System.Messaging, let's build two simple applications: one to enqueue messages onto a private queue on the local computer and another to dequeue these messages from the same queue.
Here's a simple program that enqueues a Customer object onto a private queue on the local computer. Notice first that we need to include the System.Messaging namespace because it contains the classes that we want to use:
using System;
using System.Messaging;
            
While the following Customer structure is very simple, it can be as complex as you want because it will be serialized into an XML-formatted buffer by default before it's placed into the queue:
public struct Customer
{
  public string Last;
  public string First;
}
Our program first checks whether a private queue on the local computer exists. If this queue is missing, the program will create it. Next, we instantiate a MessageQueue class, passing in the target queue name. Once we have this MessageQueue object, we invoke its Send( ) method, passing in the Customer object, as shown in the following code. This will put our customer object into our private queue:
public class Enqueue
{
  public static void Main(  ) 
  {
    try 
    {
      string path = ".\\PRIVATE$\\NFE_queue";
               if(!MessageQueue.Exists(path))
      {
        // Create our private queue.
        
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Summary
In this chapter, we've touched on many aspects of component-oriented programming, including deployment strategies, distributed computing, and enterprise services such as transaction management, object pooling, role-based security, and message queuing. We have to give due credit to Microsoft for making componentization easier in the .NET Framework. Case in point: without .NET, it would be impossible for us to show the complete code for all of these programs in a single chapter of a book.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 5: Data and XML
Almost everything we do in the software industry relates to data in some way. At some point, all software developers must deal with data, perhaps using a database, text file, spreadsheet, or some other method of data storage. There are many different methods and technologies for using, manipulating, and managing data, and newer methods are continually introduced to enhance existing ones. These methods range from function-based APIs to object-based frameworks and proprietary libraries.
Several years ago, it was common for a simple VB desktop application to access a private Microsoft Access database stored on the local hard disk, but this is no longer a typical scenario. Today's applications take advantage of distributed-component technologies to exploit scalability and interoperability,