
Pro CSharp And The .NET 2.0 Platform (2005) [eng]
.pdf
514 C H A P T E R 1 5 ■ U N D E R S TA N D I N G C I L A N D T H E R O L E O F DY N A M I C A S S E M B L I E S
Summary
This chapter provided an overview of the syntax and semantics of CIL. Unlike higher-level managed languages such as C#, CIL does not simply define a set of keywords, but provides directives (used to define the structure of an assembly and its types), attributes (which further qualify a given directive), and opcodes (which are used to implementation type members). You were introduced to the CIL compiler (ilasm.exe) and learned how to alter the contents of a .NET assembly with new CIL code and also the basic process of building a .NET assembly using raw CIL.
The latter half of this chapter introduced you to the System.Reflection.Emit namespace. Using these types, you are able to emit a .NET assembly on the fly to memory. As well, if you so choose, you may persist this in-memory image to a physical file. Recall that many types of System.Reflection.Emit will automatically generate the correct CIL directives and attributes using friendly types such as ConstructorBuilder, TypeBuilder, and so forth. The ILGenerator type can be used to inject the necessary CIL opcodes into a given member. While we do have a number of helper types that attempt to make the process of programming with the CIL opcode set more palatable, you must have an understanding of CIL when programming with dynamic assemblies.

P A R T 4
■ ■ ■
Programming with the
.NET Libraries





520 C H A P T E R 1 6 ■ T H E S YS T E M . I O N A M E S PA C E
Table 16-3. (Continued )
Members |
Meaning in Life |
GetFiles() |
Retrieves an array of FileInfo types that represent a set of files in the |
|
given directory |
MoveTo() |
Moves a directory and its contents to a new path |
Parent |
Retrieves the parent directory of the specified path |
Root |
Gets the root portion of a path |
|
|
You begin working with the DirectoryInfo type by specifying a particular directory path as a constructor parameter. If you want to obtain access to the current application directory (i.e., the directory of the executing application), use the "." notation. Here are some examples:
//Bind to the current application directory.
DirectoryInfo dir1 = new DirectoryInfo(".");
//Bind to C:\Windows,
//using a verbatim string.
DirectoryInfo dir2 = new DirectoryInfo(@"C:\Windows");
In the second example, you are making the assumption that the path passed into the constructor (C:\Windows) already exists on the physical machine. However, if you attempt to interact with a nonexistent directory, a System.IO.DirectoryNotFoundException is thrown. Thus, if you specify a directory that is not yet created, you will need to call the Create() method before proceeding:
// Bind to a nonexistent directory, then create it.
DirectoryInfo dir3 = new DirectoryInfo(@"C:\Windows\Testing"); dir3.Create();
Once you have created a DirectoryInfo object, you can investigate the underlying directory contents using any of the properties inherited from FileSystemInfo. To illustrate, the following class creates a new DirectoryInfo object mapped to C:\Windows (adjust your path if need be) and displays a number of interesting statistics (see Figure 16-2 for output):
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Directory(Info) *****\n");
DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");
// Dump directory information.
Console.WriteLine("***** Directory Info *****");
Console.WriteLine("FullName: {0} ", dir.FullName); Console.WriteLine("Name: {0} ", dir.Name); Console.WriteLine("Parent: {0} ", dir.Parent); Console.WriteLine("Creation: {0} ", dir.CreationTime); Console.WriteLine("Attributes: {0} ", dir.Attributes); Console.WriteLine("Root: {0} ", dir.Root); Console.WriteLine("**************************\n");
}
}

C H A P T E R 1 6 ■ T H E S YS T E M . I O N A M E S PA C E |
521 |
Figure 16-2. Information about your Windows directory
The FileAttributes Enumeration
The Attributes property exposed by FileSystemInfo provides various traits for the current directory or file, all of which are represented by the FileAttributes enumeration (enum). While the names of this enum are fairly self-describing, some of the less obvious names are documented here (consult the .NET Framework 2.0 SDK documentation for full details):
public enum FileAttributes
{
ReadOnly,
Hidden,
//The file is part of the operating system or is used
//exclusively by the operating system
System,
Directory,
Archive,
//This name is reserved for future use.
Device,
//The file is 'normal' as it has no other attributes set.
Normal,
Temporary,
//Sparse files are typically large files whose data are mostly zeros.
SparseFile,
//A block of user-defined data associated with a file or a directory
ReparsePoint,
Compressed,
Offline,
//The file will not be indexed by the operating system's
//content indexing service.
NotContentIndexed, Encrypted
}
Enumerating Files with the DirectoryInfo Type
In addition to obtaining basic details of an existing directory, you can extend the current example to use some methods of the DirectoryInfo type. First, let’s leverage the GetFiles() method to obtain information about all *.bmp files located under the C:\Windows directory. This method returns an array of FileInfo types, each of which exposes details of a particular file (full details of the FileInfo type are explored later in this chapter):

522 C H A P T E R 1 6 ■ T H E S YS T E M . I O N A M E S PA C E
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Directory(Info) *****\n");
DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");
...
//Get all files with a *.bmp extension.
FileInfo[] bitmapFiles = dir.GetFiles("*.bmp");
//How many were found?
Console.WriteLine("Found {0} *.bmp files\n", bitmapFiles.Length);
// Now print out info for each file. foreach (FileInfo f in bitmapFiles)
{
Console.WriteLine("***************************\n"); Console.WriteLine("File name: {0} ", f.Name); Console.WriteLine("File size: {0} ", f.Length); Console.WriteLine("Creation: {0} ", f.CreationTime); Console.WriteLine("Attributes: {0} ", f.Attributes); Console.WriteLine("***************************\n");
}
}
}
Once you run the application, you see a listing something like that shown in Figure 16-3. (Your bitmaps may vary!)
Figure 16-3. Bitmap file information
Creating Subdirectories with the DirectoryInfo Type
You can programmatically extend a directory structure using the DirectoryInfo.CreateSubdirectory() method. This method can create a single subdirectory, as well as multiple nested subdirectories, in a single function call. To illustrate, here is a block of code that extends the directory structure of C:\Windows with some custom subdirectories:

C H A P T E R 1 6 ■ T H E S YS T E M . I O N A M E S PA C E |
523 |
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Directory(Info) *****\n");
DirectoryInfo dir = new DirectoryInfo(@"C:\Windows");
...
//Create \MyFoo off initial directory. dir.CreateSubdirectory("MyFoo");
//Create \MyBar\MyQaaz off initial directory. dir.CreateSubdirectory(@"MyBar\MyQaaz");
}
}
If you examine your Windows directory using Windows Explorer, you will see that the new subdirectories are present and accounted for (see Figure 16-4).
Figure 16-4. Creating subdirectories
Although you are not required to capture the return value of the CreateSubdirectory() method, be aware that a DirectoryInfo type representing the newly created item is passed back on successful execution:
// CreateSubdirectory() returns a DirectoryInfo item representing the new item.
DirectoryInfo d = dir.CreateSubdirectory("MyFoo"); Console.WriteLine("Created: {0} ", d.FullName);
d = dir. CreateSubdirectory(@"MyBar\MyQaaz"); Console.WriteLine("Created: {0} ", d.FullName);
Working with the Directory Type
Now that you have seen the DirectoryInfo type in action, you can learn about the Directory type. For the most part, the members of Directory mimic the functionality provided by the instance-level members defined by DirectoryInfo. Recall, however, that the members of Directory typically return string types rather than strongly typed FileInfo/DirectoryInfo types.
To illustrate some functionality of the Directory type, the final iteration of this example displays the names of all drives mapped to the current computer (via the Directory.GetLogicalDrives() method) and uses the static Directory.Delete() method to remove the \MyFoo and \MyBar\MyQaaz subdirectories previously created: