Você está na página 1de 27

Input and Output: System.

IO
Like most software, .NET Framework applications need some way to input and output data. These operations are most commonly done against a disk drive, but there are other possibilities too. The .NET Framework class library's ystem.!" namespace contains a substantial set of types that developers can use to read and write files, work with directories in a file system, and do other kinds of straightforward data access. File access is an essential service #mong the most fundamental of these types is the tream class. #s defined by this class, a stream is a se$uence of bytes together with methods to read the stream's contents, write those contents, perhaps seek to a specific location in the stream, and perform other operations. A Stream object contains a sequence of bytes and provides methods to access those bytes For e%ample, information stored in files can be accessed using the File class. &hile an instance of File provides familiar methods for working with files such as Create, Delete, and Open, it doesn't provide methods for reading and writing a file's contents. !nstead, a File ob'ect's (reate and "pen methods return an instance of a FileStream that can be used to get at the file's contents. Like all streams, a FileStream ob'ect provides Read and Write methods for synchronous access to a file's data, that is, for calls that block waiting for data to be read or written. #lso like other streams, FileStream ob'ects allow asynchronous access using the paired BeginRead/EndRead and BeginWrite/EndWrite methods. These methods allow a .NET Framework application to begin a read or write operation and then check later to get the result. Each FileStream also provides a eek method to move to a designated point in the file, a Flush method to write data to the underlying device )such as a disk drive*, a Close method to close the FileStream, and many more methods. A FileStream object allows access to a file's contents as binary data File treams work only with binary data, however, which isn't always what's needed. ystem.!" provides other standard classes to work with file data in other formats. For e%ample, the FileIn o class can be used to create FileStreams, but it can also be used to create instances of the classes StreamReader and StreamWriter. +nlike File, whose methods are mostly static, an instance of a File!nfo class must be e%plicitly created before its methods can be used. "nce a File!nfo ob'ect e%ists, its Open!e"t method can be used to create a new StreamReader ob'ect. This StreamReader can then be used to read characters from whatever file is associated with the FileIn o ob'ect. A FileInfo object allows access to a file's contents as text ,ere's a (- e%ample that illustrates how these classes can be used.
using System; using System.IO;

class FileIOExample { static void Main() { FileStream fs; FileInfo f; Stream eader sr; !yte"# !uf $ ne% !yte"&'#; string s; int i; for (i$'; i(&'; i))) !uf"i# $ (!yte) (*+ ) i); fs $ File.,reate(-test.dat-); fs..rite(!uf/ '/ &'); fs.,lose(); f $ ne% FileInfo(-test.dat-); sr $ f.Open0ext(); s $ sr. ead0oEnd(); 2 2 ,onsole..rite1ine(-{ '2 -/ s);

This admittedly unrealistic e%ample begins with appropriate using statements and then defines the single class File!"E%ample. This class contains only a /ain method, which begins with several declarations. #fter this, the 012byte buffer buf is populated with the characters 3#4 through 35.4 6ecause buf can accept only bytes, this is done by e%plicitly calculating each character's value and then forcing the result to be of type byte. )This forced type conversion is called casting.* File's (reate method is then used to create a file, followed by a call to File's &rite method. This method writes buf's ten characters into that file and is followed by a (lose call that closes the file. 6ecause the File class declares all of these methods to be static, they can be invoked without e%plicitly creating a File instance. The e%ample ne%t opens the same file using an instance of the File!nfo class. (alling the File!nfo ob'ect's "penTe%t method returns a tream7eader ob'ect whose 7eadToEnd method can be used to read the characters 'ust written into a string. tream7eaders also provide methods to read single characters, blocks of characters, and lines of characters. Finally, the characters read from the file are written to the console, yielding the result
34,5EF67I8

ystem.!" also defines several other useful types. The 8irectory class, for instance, provides methods such as (reate8irectory to create a new directory, 8elete to destroy an e%isting directory and its contents, and several more. The /emory tream class allows the typical operations defined for a stream, such as 7ead, &rite, and eek, to be carried out on an arbitrary set of bytes in memory. tring&riter and tring7eader provide analogous functions to tream&riter and tream7eader, e%cept that instead of working with files, they work with in2

memory strings. 6inary7eader and 6inary&riter allow reading and writing values of types such as integers, decimals, and characters from a stream. any other classes are also defined for wor!ing with files" directories" and streams &hile information stored in relational databases is more important for many applications, data stored in files still matters. The classes in ystem.!" provide a fle%ible set of options for working with that data.

Seriali#ation: System.Runtime.Seriali#ation
"b'ects commonly have state. #n instance of a class, for e%ample, can have one or more fields, each of which contains some value. !t's often useful to e%tract this state from an ob'ect, either to store the state somewhere or to send it across a network. 9erforming this e%traction is called seriali#ing an ob'ect, while the reverse process, recreating an ob'ect from seriali:ed state, is known as deseriali#ing Seriali#ation extracts an object's state The .NET Framework class library provides support for seriali:ation. The work of seriali:ation is done by a particular formatter$ each formatter provides a eriali:e and 8eseriali:e method. The NET Framework class library provides two varieties of formatter. The binary formatter, implemented by the 6inaryFormatter class in the System.Runtime.Seriali#ation.Formatters.Binary namespace, seriali:es an ob'ect into a straightforward binary form designed to be compact and $uick to parse. The "#9 formatter, implemented by the oapFormatter class in the System.Runtime.Seriali#ation.Formatters.Soap namespace, seriali:es an ob'ect into a "#9 message. A formatter can be used to seriali#e an object Figure ;20 illustrates the seriali:ation process. #s the figure shows, an instance of a class can be run through a formatter that e%tracts the state of this ob'ect in a particular form. #s 'ust stated, the binary formatter emits that state information in a simple and compact form, while the "#9 formatter generates the same information wrapped in </L and formatted as a "#9 message. &hile the outputs shown in the figure are simplified=the binary formatter actually stores integers in binary form, for instance=they illustrate the key difference between the two seriali:ation options built into the .NET Framework class library.

Figure 5-1. The System.Runtime.Serialization namespace provides two different formatters to serialize an ob ect!s state.

%oth a binary formatter and a S&A' formatter are provided &hen a formatter seriali:es an ob'ect, the resulting state is placed into a stream. #s described in the previous section, a stream is an abstraction of a se$uence of bytes and so can hold any seriali:ation format. "nce it's in a stream, an ob'ect's state can be stored on disk )or in the 'argon of ob'ects, be made persistent*, sent across a network to another machine, or used in some other way. An object's state is seriali#ed into a stream For a type to be seriali:able, its creator must mark it with the eriali:able attribute, as Figure ;20 illustrates. The eriali:able attribute can be assigned to classes, structures, and other types or 'ust to specific fields within a type to indicate that only they should be seriali:ed. #lso, a type marked with the eriali:able attribute can indicate that certain fields should not be saved when an instance of this type is seriali:ed by marking them with the Non eriali:ed attribute. (ot every type is seriali#able eriali:ation can also be customi:ed. For e%ample, if a class implements the ! eriali:able interface, it can participate in its own seriali:ation. This interface has only a single method that allows controlling the details of what gets seriali:ed. #lso, although it's not shown in this simple e%ample, seriali:ing an ob'ect will also seriali:e ob'ects it refers to, causing them all to be

seriali:ed )or deseriali:ed* at once. #nd for the brave of heart, it's possible to build your own formatter that does seriali:ation in a completely customi:ed way by inheriting from the abstract class ystem.7untime. eriali:ation.Formatter. ,owever it's done, seriali:ation is useful, and in its basic form, at least, it's simple to use. #s described later in this chapter, seriali:ation plays a role in several parts of the .NET Framework class library.

Wor$ing %it& '(): System.'ml


</L is certainly among the most important new technologies to emerge in the last few years. #ccordingly, the .NET Framework class library includes a substantial amount of support for working with </L, most of it contained in the System.'ml namespace. icrosoft has gotten ) * religion

The XML Technology Family


. To get a feeling for what the System.'ml namespace provides, however, you need to understand a bit more about the family of </L technologies. </L has evolved into a significantly more powerful=and more comple%=group of technologies. ) * is more than angle brac!ets
XML Infosets

The familiar angle bracket form of </L implies a logical hierarchy of related information. This abstract set of information and relationships is known as the </L document's Information Set" a term that's usually shortened to 'ust Infoset. #n In oset consists of some number of information items" each of which represents some aspect of the </L document from which this !nfoset was derived. For e%ample, every !nfoset has a document information item that acts as the root of the tree, with a single root element information item 'ust beneath it. /ost !nfosets have some number of child element information items below this root element. An Infoset provides an abstract view of the information in an ) * document For e%ample, consider this simple </L document.
(employees9 (employee9 (name94o!(:name9 (age9;*(:age9 (:employee9 (employee9 (name9,asey(:name9 (:employee9 (:employees9

The !nfoset for this document can be represented as shown in Figure ;2>. The root of the !nfoset's tree is a document information item, while below it is a hierarchy of element information items, one for each element in the </L document. The leaves of the tree are the values of the elements in this simple document.
Figure 5-". #n $%& document!s 'nfoset is an abstract representation of the document!s contents.

(ther $%& Technologies

</L documents and the !nfosets they imply can provide the foundation for tools that manipulate a document's data. #mong the most important of these is <9ath, which provides a mechanism for identifying a subset of an !nfoset. # simple and $uite accurate way to think of <9ath is as a $uery language for information in </L documents )that is, for </L !nfosets*. 5ust as ?L provides a standard language for $uerying information contained in a relational database, <9ath provides a language for $uerying information represented as a hierarchy. +sing an <9ath e%pression, a user can identify specific nodes in a tree. XPath allows querying an ) * document For e%ample, imagine that this $uery is issued against the simple </L document 'ust described.
:employees:employee:name

This simple <9ath re$uest first identifies each employee element below the root employees element and then identifies the values of each name element in each of those employee elements.

&ith <9ath, a developer need not write her own code to search through information. !nstead, this abstract language can be used to find easily information represented as an in2memory </L document. #nother technology built on the abstract foundation provided by </L In osets is the E"tensi*le Styles&eet )anguage !rans ormations, universally referred to as < LT. < LT is a mechanism for specifying transformations of </L documents, transformations that can be described in an < LT stylesheet. For instance, a set of < LT rules that transforms an </L document from one schema to another can be defined. < LT also relies on the abstract form of an </L document represented by its !nfoset, and it relies on <9ath for some of its functionality. )S*+ allows transforming ) * documents Figure ;2@ summari:es the relationships among the fundamental </L technologies. #n </L chema definition describes the structure and contents of an </L document=it defines a group of types=while an </L document itself can be thought of as an instance of the document type defined by some schema. This </L document, in turn, is the foundation for an !nfoset, which provides an abstract view of the document's data. Technologies for working with that data, such as <9ath and < LT, are effectively defined to work against the !nfoset, allowing them to remain independent of the specific representation used for the </L document itself. Note that because these technologies rely on the !nfoset rather than the familiar angle bracketAbased synta% of an </L document, they can actually be used with any data that can be represented in a strict hierarchy. That data need not necessarily come from a traditional </L document as long as it can be represented as an !nfoset. For e%ample, hierarchical data such as a file system or the &indows registry might be accessed in this way.

Figure 5-). $%& is a family of technologies* with the 'nfoset at the center.

) * today is a unified family of technologies


$%& #+'s

The </L standards don't mandate any particular approach to processing the information in an </L document. #s it happens, two styles of #9!s have come into common use. !n one approach, the information in an </L document is read se$uentially, traversing a document's tree in a depth2first search. #n #9! that supports this kind of access is referred to as a streaming #9!, SA) is a streaming A'I for accessing ) *,defined information !n the second approach, the entire document is represented as an in2memory data structure )conceptually, at least*, which allows an application to navigate through it, moving back and forth as needed. The most commonly used #9! for this option is an implementation of the 8ocument "b'ect /odel )8"/* defined by the &@(. 6ecause of the style of access it allows, the 8"/ is an e%ample of a navigational #9!. +he -& is a navigational A'I for accessing ) *,defined information

What System.Xml Provides


The ystem.<ml namespace has a great deal of built2in support for working with </L. #mong the features available are support for both streaming and navigational #9!s, the ability to use

<9ath $ueries, the ability to perform < LT transformations, and more. System.)ml includes support for )'ath" )S*+" the -& " and more The most fundamental types for handling </L2defined data are contained directly in ystem.<ml itself. "ne of these is the abstract class <mlNode. #s its name suggests, this class represents a node in an </L document, such as a particular element. #nother fundamental type in ystem.<ml is the abstract class <ml7eader. <ml7eader provides a streaming interface for accessing </L data. )Note that the .NET Framework does not directly support #<B instead it bases all streaming access on <ml7eader.* <ml7eader is the parent for three concrete classes.

'ml!e"tReader: 9rovides a streaming #9! that reads the information in an </L document se$uentially, much like the #< #9!. !t's the fastest option for reading </L2 defined data, but it's also somewhat limited in that no navigation is possible through the document. #lso, this class makes no attempt to determine whether the document is valid, that is, whether it corresponds correctly with some </L chema definition. 'ml+alidatingReader: Like <mlTe%t7eader, this class reads the information in an </L document se$uentially. !t also makes sure that the document corresponds to a specified </L chema definition, that is, that the document is valid. 'ml,odeReader: 7ather than reading from an </L document, this class provides forward2only access to a single <mlNode or a tree of <mlNodes. This is the same in2 memory structure used to represent an </L document accessed via the 8"/, but unlike the navigational 8"/ interface, <mlNode7eader allows only se$uential access.

+he )ml.eader class allows streaming access to ) *,defined information ystem.<ml also includes an abstract <ml&riter class, along with one implementation of a concrete class, called <mlTe%t&riter, that inherits from <ml&riter. The methods in this class allow writing </L information, angle brackets and all, to a stream. #s described earlier in this chapter, a stream can be maintained in memory, written to a file, or used in some other way. +he )ml/riter class allows writing ) * documents ystem.<ml also includes the <ml8ocument class. This class, which inherits from <mlNode, provides an implementation of the 8"/ #9!. &hile the various implementations of <ml7eader 'ust described are the fastest way to access information in an </L document, the <ml8ocument class is more general because it allows navigation, moving backward and forward through the document at will. # developer is free to choose whichever approach best meets the needs of his application. An )ml-ocument object allows navigational access to ) *,defined information The methods and properties provided by <ml8ocument give some idea of the kinds of operations the 8"/ allows. Those methods include the following.

)oad: Loads an </L document and parses it into its abstract tree form

Sa-e:

aves an in2memory document to a stream, file, or some other location

InsertBe ore: !nserts a new node, represented as an instance of the <mlNode class, in front of the currently referenced node in the tree Insert. ter: !nserts a new node, once again an <mlNode instance, in back of the currently referenced node in the tree Select,odes: #llows selecting nodes using an <9ath e%pression

<ml8ocument also e%poses a number of properties that allow navigation through the tree. They include the following.

/asC&ild,odes: !ndicates whether the current node has any nodes beneath it FirstC&ild: 7eturns the first child of the current node )astC&ild: 7eturns the last child of the current node 0arent,ode: 7eturns the parent, that is, the node immediately above the current node

everal other namespaces are defined beneath ystem.<ml.

System.'ml.Sc&ema: (ontains classes for creating and working with </L chema definitions. 6ecause this language is $uite comple%, this namespace contains a large set of classes, including a class for each of the elements in the </L chema language. /icrosoft refers to these classes collectively as the chema "b'ect /odel ) "/*. System.'ml.'0at&: (ontains types that support using <9ath e%pressions to $uery hierarchical data. #mong them are the <9athNavigator class, which allows navigating through a document and issuing <9ath $ueries, and the <9athE%pression class, which can contain a compiled <9ath $uery. System.'ml.'sl: (ontains types that support using < LT. The most important of these is the <slTransform class, which allows transforming data using an < LT stylesheet. System.'ml.Seriali#ation: (ontains types that allow seriali:ing data into an </L format. This is another large namespace, but a key type within it is the <ml eriali:er class. This class is similar to the oapFormatter class described earlier, in that it provides eriali:e and 8eseriali:e methods that write and read an ob'ect's state in </L. This namespace also contains many other classes that allow customi:ing the seriali:ation process, working with "#9, and other aspects of converting between state information stored in a language ob'ect and the seriali:ed </L form of that information.

+ypes for )'ath" )S*+" and ) * Schema support are provided in separate namespaces </L has become an essential part of modern computing. 6y providing a standard way to describe information, it fills an important hole in the comple%, multivendor world we live in. The

.NET Framework's large set of namespaces and types devoted to </L are intended to make this increasingly important technology significantly easier to use. +he .(0+ Framewor! class library has a great deal of support for ) *

.,E! Remoting: System.Runtime.Remoting


#llowing communication between software running on different systems is the sine $ua non of a modern computing environment. &hile providing a remote user interface in a browser is certainly important, providing a way for software running on different systems to communicate directly remains essential. Civen that &eb services provide a $uite general mechanism for communication between software on different machines, a simple2minded view might suggest that &eb services are all that's re$uired. -istributed computing is a core technology today Effective distributed computing re$uires more than 'ust &eb services, however. To see why, think about some of the limitations of standard &eb services. For one thing, an e%plicit goal of &eb services is to allow communication between different vendor implementations. Det doing this isn't free. #s described earlier in this chapter, mapping from the (L7's type system into the one defined by </L can be problematic, and depending on how it's done, this translation might lose some information. !f both parties in the communication are built using the same technology, such as the .NET Framework, there's no reason to pay this price. 6ecause using the .NET Framework at each end is a common scenario, some option that allows transmitting the complete set of (L7 types must e%ist. /eb services are necessary but not sufficient #nother problem is that the </L2based seriali:ation used in &eb services is not very efficient. &e may have to live with this for !nternet2based communication, since </L and "#9 are becoming the world's common mechanisms for e%changing information. Det for communication inside a firewall, such as on a corporate intranet, there's no need to use a relatively inefficient </L2based format for data. !nstead, a faster binary representation can be used. .NET 7emoting addresses these concerns. &hile it is possible to e%pose "#92based &eb services using .NET 7emoting, it's more likely that this part of the class library will be used when both ends of the communication are using the .NET Framework. &hether they're communicating across an intranet or over the !nternet through firewalls, the communicating systems will then have the same type system, a common set of available remoting protocols, and even the same implementation of those protocols. .(0+ .emoting focuses on communication between 1*.,based applications

#s you might e%pect, .NET 7emoting provides traditional remote procedure call )79(* functionality, allowing a client to invoke a method in a remote ob'ect and have some result returned. !t can also be used for asynchronous )nonblocking* calls, however, as well as one2way calls that have no result. The mission of .NET 7emoting is to make all of these interactions as simple yet as fle%ible as possible. .(0+ .emoting supports both synchronous and asynchronous communication

An Overview of the Remoting Process


#lthough the word remoting implies communication between different machines, it's used a bit more broadly in the .NET Framework. ,ere, remoting refers to any communication between ob'ects in different application domains, whether those app domains are on the same machine or on machines connected by a network. Figure ;2E shows a very high2level view of the ma'or components of the remoting process.
Figure 5-,. -alls to remote ob ects rely on a pro.y ob ect in the calling app domain and channel ob ects in both app domains.

.(0+ .emoting is used for communication between different app domains &hen a client, such as an instance of some class, calls a method on an ob'ect in another app domain, that call is first handled by a proxy ob'ect running in the client's app domain. The pro%y represents the remote ob'ect in the client's app domain, allowing the client to behave as if that ob'ect were running locally. The (L7 automatically creates a pro%y by using reflection to access the metadata of the remote ob'ect being accessed. )Note what this implies. The assembly containing the remote ob'ect's classes andFor interfaces must be available on the client's machine.*

1lients rely on proxy objects # pro%y eventually hands a call's information to a channel ob'ect. The channel ob'ect is responsible for using some appropriate mechanism, such as a T(9 connection, to convey the client's re$uest to the remote app domain. "nce the re$uest arrives in that app domain, a channel ob'ect running there locates the ob'ect for which this call is destined, perhaps creating it if the ob'ect isn't already running. The call is then passed to the ob'ect, which e%ecutes it and passes any results back through the same path. 1ommunication is handled by channel objects #t a high level, the process is simple. !n fact, however, there's much more going on than this simple description shows. !t's possible, for instance, to insert code that intercepts and customi:es the in2progress call at several points in the path between caller and ob'ect. The details get $uite involved=remote access is never simple to implement well=but most of the comple%ity can remain invisible to developers using .NET 7emoting. The goal of this section is to present a broad overview of how this technology works. .(0+ .emoting provides many opportunities for customi#ation

Passing nformation to Remote O!"ects


(alling a method in an ob'ect is straightforward when both the client and the ob'ect are in the same app domain. 9arameters of value types such as integers are passed by value, which means that their contents are simply copied from client to ob'ect. 9arameters of reference types, such as classes, are passed by reference, which means that a reference to the instance itself is passed=no separate copy is made. (alling a method in an ob'ect gets more complicated when the two are in different app domains, however, and so .NET 7emoting must address these complications. Even accessing a remote ob'ect's properties or fields re$uires some way to transfer information across an app domain boundary. The process of packaging values for transfer to another app domain is called marshaling, and there are several options for how it gets done. 2alues passed between app domains must be marshaled and unmarshaled "ne option is marshal by value (MBV). #s the name suggests, transferring an instance of some type using this option copies its value to the remote app domain. For this to work, a user2defined type must be seriali:able, that is, its definition must be marked with the eriali:able attribute. &hen an instance of that type is passed as a parameter in a remote call, the ob'ect's state is automatically seriali:ed and passed to the remote app domain. "nce it arrives, a new instance of that type is created and initiali:ed using the seriali:ed state of the original. )Note that the code for the type isn't passed, however, which means that for types such as classes, an assembly containing the / !L for that type must e%ist on whatever machine the ob'ect's state is passed to.* #n /6G ob'ect should usually be reasonably simple, or the cost of seriali:ing and transferring the entire ob'ect to the remote app domain will be very high. arshal by value passes the value itself to another app domain

!t's also possible to pass an instance of a reference type across an app domain boundary by reference. This option, called marshal by reference 3 %.4" is possible only if the reference type inherits from /arshal6y7ef"b'ect, a class contained in the ystem namespace. &hen an /67 ob'ect is passed across an app domain boundary, only a reference to the ob'ect is passed. This reference, which is more comple% than the one used to refer to the ob'ect in its own app domain, is used to construct a pro%y back to the original ob'ect in its home app domain. &hen code in the remote app domain references this ob'ect, such as by calling one of its methods, those references are actually sent back to the original instance of this ob'ect. 9assing /67 ob'ects as parameters makes sense in cases where the overhead of accessing the ob'ect remotely is less than the cost of making a copy of the ob'ect. arshal by reference passes only a reference to another app domain Figure ;2H illustrates the difference between /6G and /67 ob'ects. &hen ob'ect <, an /6G ob'ect in app domain 0, is passed to app domain > as a parameter on a call to ob'ect ", a copy of < is created in the remote app domain. 9assing ob'ect D, however, does not result in a copy of D being created in app domain > because D is an /67 ob'ect. !nstead, a pro%y to D is created, and all accesses to ob'ect D are sent back to the instance of D in app domain 0. )#lthough it's not shown in the picture, communication from D's pro%y back to D itself relies on channels, 'ust as described earlier.*
Figure 5-/. %arshal by value ob ects are copied when passed across an app domain boundary* while marshal by reference ob ects have a pro.y created for them in the remote app domain.

Finally, if a user2defined type isn't seriali:able and doesn't inherit from /arshal6y7ef"b'ect, it is neither an /6G nor an /67 ob'ect. !n this case, instances of that type can't be marshaled across an app domain boundary at all. !n other words, any instance of this type can be used only within the app domain in which it is created. (ot all types can be marshaled

#hoosing a #hannel
#pplications using .NET 7emoting ultimately rely on channels to convey calls and responses between app domains. Two standard channels, called the +1' channel and the 5++' channel" are provided, and it's also possible to build custom channels. .(0+ .emoting provides a +1' channel and an 5++' channel &hile not especially simple to create, a custom channel might provide security services such as encryption, use a nonstandard protocol, or perform some other function in a uni$ue way. !t's safe to assume, however, that most applications will work happily with one of the two choices built into the .NET Framework. The !C0 c&annel is the simpler of the two. 6y default, it seriali:es and deseriali:es a call's parameters using the binary formatter described earlier in this chapter, although the "#9 formatter can also be used. "nce the parameters have been seriali:ed, they're transmitted directly in T(9 packets. omewhat surprisingly, the T(9 channel provides no built2in support for authentication, data encryption, or any other security feature. +he +1' channel sends binary information directly over +1' The second option, the /!!0 c&annel, uses the "#9 formatter by default to seriali:e and deseriali:e a call's parameters. 7ather than sending those parameters directly over T(9, they're sent as "#9 re$uests and responses embedded in ,TT9. !t's also possible to use the binary formatter with the ,TT9 channel, which can be very useful. The binary formatter is more efficient than the "#9 formatter, so if the .NET Framework is on both sides of the communication, this option makes sense. For applications that need distributed security, the ,TT9 channel can use the security options provided by !nternet !nformation ervices )!! *. !n this case, one possibility is to use the ecure ockets Layer ) LL* protocol with ,TT9, an option sometimes referred to as ,TT9 . +he 5++' channel sends S&A' envelopes over 5++' 8eciding which channel to use depends on your goals. !f the communication is entirely within an organi:ation's intranet=if no firewalls will be traversed=use the fast and simple T(9 channel. !f the communication must go through firewalls, however, as do most packets sent on the !nternet, use the ,TT9 channel. #lthough it's a bit less efficient, riding on ,TT9 means passing through port I1, the only port that virtually all firewalls leave open /hich channel is best depends on the situation !t's also possible to use different kinds of channels from the same app domain. This allows clients to communicate with remote ob'ects using the mechanism that's most appropriate for each one. # single client, for instance, might use the more efficient T(9 channel to talk to an ob'ect within the firewall while also invoking methods in an ob'ect across the !nternet via the ,TT9 channel.

#reating and $estroying Remote O!"ects


"ne of the most challenging issues in designing a remoting technology is determining what options to support for creating remote ob'ects, referred to as activation. .NET 7emoting provides three options, each of which is illustrated in Figure ;2I.
Figure 5-0. (b ects accessed via .12T Remoting can be single-call* singleton* or client-activated.

.(0+ .emoting provides three styles of activation for remote objects


Single1call o*2ects: # new instance of the class is created for each call from each client and then is destroyed )that is, made available for garbage collection* when the call ends. Singleton o*2ects: "nly one instance of the class is created on a given machine, and that same instance handles all calls made by all clients to that class on this machine. Client1acti-ated o*2ects: # separate instance of the class is created for each client that wishes to use it and then is destroyed only when that client is finished with it.

7egardless of which option is chosen, the server will create each new ob'ect on its own thread. #lso, any ob'ect that will be accessed from outside its app domain must be an /67 ob'ect, which means that the class must inherit from /arshal6y7ef"b'ect. These similarities notwithstanding, how ever, each of these options varies in who creates the ob'ect, how the ob'ect is destroyed, as well as in other ways. #ccordingly, each is worthy of its own short discussion.

Enterprise Ser-ices: System.EnterpriseSer-ices


/odern multitier applications often locate the bulk of their business logic in the middle tier. /uch of the time, writing this logic with a technology such as # 9.NET is perfectly ade$uate. !n some cases, however, especially for applications that need to be very scalable and re$uire features such as distributed transactions, more is re$uired. 9rior to .NET, the /icrosoft technology that provided these services was known as ("/J. &ith the advent of the .NET Framework, those services are still available to (L72based applications. !n fact, the services themselves haven't changed at all, but two things about them have. how they're accessed and what they're called. Now commonly referred to as Enterprise ervices, the traditional ("/J services for building robust, scalable applications are also usable by applications written on the .NET Framework. +he types in System.0nterprise,Services allow access to 1& 6 services Through the classes in the ystem.Enterprise ervices namespace, all ("/J services that are available to &indows 8N# applications on &indows >111 are also available to .NET FrameworkAbased applications. +nlike most of the .NET Framework, however, the code that provides ("/J services was not rewritten as managed code. /icrosoft tells us that this rewrite will happen eventually, but in the Framework's first release, the classes in ystem.Enterprise ervices provide a wrapper around the e%isting implementation that allows managed ob'ects access to these services in a natural way. All traditional 1& 6 services are available For a class to use ("/J services, that class must inherit from Enterprise ervices. erviced(omponent. 6ecause of this, a class using these services is referred to as a serviced component. erviced components have access to the full range of services ("/J provides, including the following.

upport for )possibly distributed* transactions 5ust2in2time activation )5!T#*, which optimi:es server resources by allowing ob'ects to e%ist only when they're needed "b'ect pooling, which allows instances of a class to be pooled and reused rather than being destroyed and recreated 7ole2based authori:ation services that allow ("/J to verify a client's role and then grant services only to clients in specific roles

1lasses that use 1& 6 services are !nown as serviced components erviced components can also use ("/J services that aren't directly related to building robust server applications, such as $ueued components, which is effectively an #9! to /icrosoft /essage ?ueuing )/ /?*B an event serviceB and others.The key point is that .NET Enterprise ervices allows managed code to use all ("/J services, but those services are unchanged= the .NET Framework doesn't add any new features in this area. "ne of the innovations brought by ("/J )or more correctly, by /icrosoft Transaction erver, the original incarnation of this technology* was the ability to control what services a component received by setting attributes in a configuration file. To control how transactions are used, for e%ample, a developer using ("/J can set a transaction attribute to 7e$uired, indicating that all methods in this component should be run within a transaction. &hen the component is e%ecuted, ("/J reads this attribute and provides the re$uested transaction support. !n traditional ("/J, these attributes are stored in something called the ("/J catalog, and they're typically set using the ("/J E%plorer, a configuration tool designed for this purpose. +raditional 1& 6 uses attributes to specify what services an application needs !n the .NET Framework, however, attributes are supported directly. #s every assembly can have e%tra metadata represented as attributes. #lso, attribute values can be set in the source code of a (L72based application=there's no need for a separate configuration tool=and those values can be read at runtime using reflection. 6uilt2in support for attributes matches well with how ("/J provides its services, and so .NET's Enterprise ervices e%ploit this feature of the (L7. 8evelopers are now able to specify how ("/J services should be used by including attributes directly in their code. #nd because it's sometimes useful to be able to change a component's attributes after the assembly that contains it has been installed, the ("/J E%plorer can still be used to set or modify a component's attributes if desired. Serviced components use the 1*.'s built,in attributes to specify what services an application needs ,ere's a simple G6.NET class that shows how attributes can be used to control the use of ("/J transactions.
(0ransaction(0ransactionOption. e<uired)9 = >u!lic ,lass 4an?3ccount In@erits Serviced,omponent (3uto,omplete()9 = >u!lic Su! 5eposit(3ccount 3s Integer/ = 3mount 3s 5ecimal) A 3dd 3mount to 3ccount End Su! (3uto,omplete()9 = >u!lic Su! .it@dra%al(3ccount 3s Integer/ = 3mount 3s 5ecimal) A Su!tract 3mount from 3ccount

End Su! End ,lass

This class, called 6ank#ccount, inherits from erviced(omponent, as is re$uired for any (L72 based class that wishes to use ("/J services. The class definition is also preceded with an attribute indicating that this class uses the 7e$uired setting for transactions. This means that whenever a client calls one of the class's methods, ("/J will automatically wrap the work done by that method in the all2or2nothing embrace of a transaction. The two methods in this simple class, 8eposit and &ithdrawal, each begins with the #uto(omplete attribute )and since this is 'ust an e%ample, the code for these methods is omitted*. This attribute indicates that if the method returns an e%ception, the serviced component will vote to abort the transaction of which it's a part. !f the method completes normally, however, this component will vote to commit the transaction to which it belongs. Note that different attributes are applied at different levels. The Transaction attribute, for e%ample, can be applied only to a class=it can't be set per method=while #uto(omplete can be applied only on a per2method basis. !f the developer of this application wished to add a method to check the balance, she might well choose to put this method in some other class. #dding it to the 6ank#ccount class would re$uire the method to use a transaction, which isn't generally necessary for this kind of simple read operation so it would needlessly hurt performance. Attributes can be used to specify a class's transactional requirements /any other attributes are available for controlling aspects of a serviced component's behavior. For e%ample, the 5ust!nTime#ctivation attribute allows turning 'ust2in2time activation on and off )although this feature is automatically turned on for classes that use transactions*, while the "b'ect9ooling attribute controls whether pooling is used and, if it is, how large the pool will be. "ther available attributes set application2wide options such as the name of the application as seen by ("/J. Attributes can also be used to specify the use of other 1& 6 services !n standard ("/J, an interface called !"b'ect(onte%t contains fundamental methods that components can use. 9erhaps the most important of these are et(omplete and et#bort, the two methods that allow a component to cast its vote in a transaction if the autocomplete option isn't used. !n .NET Enterprise ervices, these same methods are available through a class called (onte%t+til. !f a transactional method wishes to control its commitment behavior e%plicitly, it can do so by directly calling these methods. +he methods in the traditional I&bject1ontext interface are still available #s mentioned earlier, the implementation of ("/J services is not managed code in the first release of the .NET Framework. !n spite of this, serviced components are able to use those services without leaving the managed environment. #s Figure ;2K shows, key ("/J services such as transactions are provided using conte%t information maintained by ("/J itself in un managed code. &hen this conte%t is accessed, such as when a serviced component votes to commit or abort a transaction, that re$uest flows across the boundary between managed and

unmanaged code. !nteractions among serviced components, however, remain completely within the managed environment provided by the (L7. ince crossing into unmanaged code incurs a slight performance penalty, this ability to remain almost entirely within the managed space is a good thing.
Figure 5-3. -(%4 maintains conte.t information for serviced components* allowing it to provide services across the managed5unmanaged boundary.

1& 6 has not been completely rewritten as managed code Enterprise ervices also has a few more artifacts of its foundation in unmanaged code. For e%ample, when a serviced component is accessed remotely, that access relies on 8("/ rather than on .NET 7emoting. imilarly, serviced components must have entries in the &indows registry, like traditional ("/J components but unlike other .NET classes. These entries can be created and updated automatically by the Enterprise ervices infrastructure=there's no need to create them manually=but re$uiring them at all betrays this technology's ("/ foundations. !t's likely that all of these limitations will change in a future release of the .NET Framework when ("/J is completely rewritten in managed code. .emote access to serviced components is via -1&

Interopera*ility: System.Runtime.InteropSer-ices
&indows 8N# is a successful group of technologies. Lots of applications that were built using ("/, #ctive erver 9ages, ("/J, and the rest of the 8N# family e%ist. /any of these applications play an important role in running businesses, so they're certain to remain in use for at least the ne%t few years. No matter how successful the .NET Framework is, the &indows 8N# technologies that preceded it are not going away anytime soon. Software using pre,.(0+ technologies will not just disappear Civen the huge investment /icrosoft's customers have made in these applications, the .NET Framework must provide some way for new applications to connect with them. 5ust as important, the Framework must provide an effective way for managed code to access e%isting 8LLs that weren't built using ("/ and to invoke the raw services provided by the underlying operating system. olutions to all of these problems are provided by the classes in the ystem.7untime.!nterop ervices namespace. +he types in System..untime.,InteropServices allow interoperability with existing software

Accessing #OM O!"ects


The problem of interoperating with ("/ ob'ects is in some ways similar to an issue we've seen earlier in this chapter. translating from one type system to another. 5ust as mapping between the (L7's type system and that defined by </L is problematic, so is mapping between the (L7 type system and that defined by ("/. Dou might e%pect mapping to ("/ to be a bit easier, since both the (L7 and ("/ are /icrosoft2owned technologies. Det the truth is that even though /icrosoft owns it, ("/ is fro:en in stone. The millions of lines of e%isting ("/2based code in the world won't change to accommodate the new type system of the (L7, so the .NET Framework's solution for ("/ interoperability must adapt itself to the reality of the installed base. A !ey aspect of interoperability is mapping from 1& types to 1*. types

8oing this can be simple. !n some cases, mapping from a ("/ interface to a (L7 type is straightforward. !t can also be $uite difficult, however, especially when the ("/ interface involved uses comple% types. &hile it's virtually always possible to map the two together in some way, it isn't always easy. To make even difficult mappings possible, the classes in ystem.7untime.!nterop ervices provide very fine2grained control over how the mapping is done as well as many, many options. &hile most people won't use most of these options most of the time, it's still good to know that they're available. apping between 1& and managed objects can be simple" but it can also be complex

The fundamental model for interoperation between managed code and ("/2based code is that each side sees the other in the form it e%pects. /anaged code sees ("/2based code as managed types, while ("/2based code sees managed code as ("/ ob'ects. ,ow this looks is shown in Figure ;201. To provide this illusion, the .NET Framework relies on two kinds of wrappers. "ne, known as a runtime callable wrapper 3.1/4" allows managed code to call a ("/ ob'ect. The other, a 1& callable wrapper 311/4" allows ("/ code to access managed code.
Figure 5-16. The .12T Framewor7!s -(% interoperability services can ma7e a -(% ob ect loo7 li7e managed code and managed code loo7 li7e a -(% ob ect.

Interoperability lets 1&

code and managed code each see the other as being li!e themselves

6ut where does the information needed to create these wrappers come fromL /anaged code sees the world in terms of assemblies, so to access a ("/ ob'ect as managed code, an assembly that mimics the ("/ class must e%ist. Furthermore, this assembly must contain metadata that accurately reflects the ("/ class's interfaces. To create this interoperability assembly, the .NET Framework provides a tool called Tlbimp, also known as the Type Library !mporter. The input to this tool is a ("/ type library, and the output is an assembly that contains metadata for the (L7 analogs of the ("/ types in the type library. +ools create wrappers for 1& objects

"nce this assembly has been created, managed code can treat the library's ("/ classes 'ust like any other managed code. &hen the managed code creates an instance of the class, the 7(& actually creates the ("/ ob'ect. &hen the managed code invokes a method, the 7(& makes a corresponding method invocation on the ("/ ob'ect. !f an error occurs and the ("/ method returns an error ,7E +LT, as ("/ re$uires, the 7(& automatically turns this into an

e%ception that can be caught by the managed code. #nd when the managed code is finished using the ob'ect, it can behave 'ust as it does when using any other managed ob'ect. The 7(& will decrement the ("/ ob'ect's reference count before it is itself destroyed by the (L7's garbage collector. +he wrapper maps between 1& 's behavior and what managed code expects &hen a ("/ client uses a managed class, the same kinds of things happen in the opposite direction. 7ather than producing an assembly from a type library, the developer can now produce a type library from an assembly. The Type Library E%porter tool, known as Tlbe%p, provides one way to do this. #lso, because ("/ uses the registry to determine which code should be loaded for a particular class, assemblies that will be accessed by ("/ clients must have appropriate registry entries. The #ssembly 7egistration Tool, 7egasm, can be used to do this and optionally to register the assembly's generated type library as well. &hen a ("/ client creates and uses an instance of a managed class, translations between the two worlds are performed as before, but this time they're done by the ((& rather than the 7(&. +ools also create wrappers for managed objects #ll of this sounds simple and straightforward, and it often is. Det what's not been addressed so far is the process of converting between the (L7 type system and the ("/ type system. /uch as with .NET 7emoting, data must be marshaled between the two environments by the wrappers. 8efault mappings are defined, and if those defaults work, using code from the other world is simple. /arshaling an integer, for e%ample, is straightforward, since a value of this type is the same in both environments. !f the default mappings aren't appropriate, however, a developer's life gets more comple%. &hat should a (L7 string map to in the ("/ world, for e%ampleL ("/ has more than one string format, and it's not always obvious which one should be used. To control this and other marshaling choices, a developer can use the /arshal#s attribute to indicate the choice she prefers. Figuring out the right thing to do isn't always easy, but the fine2grained control the types in this namespace provide at least makes it possible. A developer can customi#e the mapping between these two environments "ne last point worth noting is that making calls across the boundary between managed and unmanaged code is noticeably more e%pensive than making calls solely within either environment. /arshaling data between the two takes timeB writing managed code that interoperates with unmanaged code has performance implications. !t's a good idea to do as much work as possible on each call across this boundary. !f each one does only a small amount of work, an application that makes a large number of calls between the two worlds is unlikely to perform especially well. 1alls between managed and unmanaged code are expensive

Accessing %on&#OM $LLs


&hile much of the e%isting code a .NET Framework application needs to use is accessible as ("/ classes, much of it isn't. 9lenty of useful 8LLs that don't use ("/ have been created. "ne important e%ample of this is the &in@> #9!, e%posed as a set of 8LLs that allow direct access to &indows services. To allow managed code to call functions in these 8LLs, the .NET Framework provides what are called platform invo!e services, a phrase that's commonly shortened to 'ust 'Invo!e. 'Invo!e allows managed code to call existing -**s To use these services, a developer must specify the name of some 8LL he wishes to use, the entry point to be called, the parameter list, and possibly other information. ,ow this is done varies with the language in use. !n G6.NET, for e%ample, the 8eclare statement is used, while (- relies on an attribute called 8ll!mport. &hichever choice is made, once a 8LL function has been appropriately specified, it can be invoked as if it were a function in a managed ob'ect. The platform invoke services provide the necessary translations, including marshaling of parameter types, to carry out the call. ystem.7untime.!nterop ervices is a critically important part of the .NET Framework class library. #lthough the notion of legacy software is sometimes viewed pe'oratively, it has one enormous thing going for it. &e know it works. !f new code written on the .NET Framework had no way to communicate with the installed base, this new platform would have been much less attractive. The Framework's strong support for interoperability with e%isting code recogni:es this reality, doing its part to smooth the transition to the brave new .NET world. Interoperability is an essential feature of the .(0+ Framewor!

Windo%s 34Is: System.Windo%s.Forms


!t can sometimes seem as if browser2based applications have taken over the world. &hile developers once devoted a great deal of time to getting the &indows C+! right, they now also sweat technical bullets over details of ,T/L and 5ava cript. 6rowsers have become the new default interface for a whole generation of software. %rowser interfaces are very common today 6ut &indows C+!s still matter. The ascendancy of browsers notwithstanding, applications that directly access pi%els on a screen are not going away. 7ecogni:ing this fact, the designers of the .NET Framework provided a new set of classes that allow (L72based applications to build &indows C+!s. (ontained in the ystem.&indows.Forms namespace, these classes are commonly referred to as &indows Forms. /indows interfaces remain important

'(ilding )* s *sing Windows Forms


tripped to its essentials, an application that presents a C+! displays a form on the screen and then waits for input from the user. This input is typically processed by a message loop, which passes the input on to the appropriate place. For e%ample, when the user clicks a button or hits a key or moves the mouse, events that are sent to the form the user is accessing are generated. The form and any code attached to it handle these events and then write output to the screen. +he typical model for a 78I is a form with code that responds to events !n &indows Forms, every form is an instance of the Form class, while the message loop that accepts and distributes events is provided by a class called #pplication. +sing these and other classes in ystem.&indows.Forms, a developer can create a single2document interface ) 8!* application, able to display only one document at a time, or a multiple2document interface )/8!* application, able to display more than one document simultaneously. /indows Forms follows the traditional model Each instance of the Form class has a large set of properties that control how that form looks on the screen. #mong them are Font, which indicates what font should be used for any te%t displayed on the formB i:e, which controls the form's initial on2screen si:eB and nearly a hundred more properties. 8evelopers can set these properties to customi:e a form's appearance and behavior. Forms have properties Forms commonly contain other classes called /indows Forms controls. Each of these controls typically displays some kind of output, accepts some input from the user, or both. The ystem.&indows.Forms namespace provides a large set of controls, many of which will be familiar to anyone who's built or even used a C+!. The control classes available in this namespace include 6utton, Te%t6o%, (heck6o%, 7adio6utton, List6o%, (ombo6o%, and many more. #lso provided are more comple% controls such as "penFile8ialog, which encapsulates the operations that let a user open a fileB aveFile8ialog, which encapsulates the operations that let a user save a fileB 9rint8ialog, which encapsulates the operations that let a user print a documentB and several others. Forms can contain /indows Forms controls Like a form, each control has properties that can be set to customi:e its appearance and behavior. /any of these come from ystem.&indows.Forms.(ontrol, a class from which every control inherits. )!n fact, even the Form class inherits from ystem.&indows.Forms.(ontrol.* The 6utton control, for e%ample, has a Location property that determines where the button will appear relative to its container, a i:e property that determines how big the on2screen button will be, and a Te%t property that controls what te%t will appear in the button. 1ontrols have properties

Forms and controls also support events. ome e%amples of common events include (lick, indicating that a mouse click has occurredB CotFocus, indicating that the form or control has been selected by the userB and Mey9ress, indicating that a key has been pressed. !n fact, all of these events and several more are defined in the base (ontrol class from which all &indows Forms controls inherit. # control can also support uni$ue events that have meaning only to it. %oth forms and controls can respond to events # developer can create code to handle events received by a form or control. (alled an event handler" this code determines what happens when the event occurs. ,andling events relies on delegates, the type provided by the (L7 for passing references to methods in a type2safe way. 1ode that responds to events is called an event handler

Windows Forms #ontrols


&indows Forms controls are a very useful way to package reusable chunks of functionality. #lthough the .NET Framework class library provides a large set of controls, the inventiveness of developers knows no bounds. #ccordingly, the .NET Framework makes it straightforward to write custom &indows Forms controls. #s already mentioned, every &indows Forms control must inherit either directly or indirectly from the class (ontrol. !t's also possible to inherit from one of the standard controls provided with the .NET Framework class library, basing a new control on e%isting functionality, or to combine two controls into one new one. &hatever choice the control's creator makes, a good chunk of the work is done for her. 6ecause the new control can be built on what the .NET Framework already provides, building one is significantly easier than it was in the &indows 8N# era. -evelopers can create custom /indows Forms controls &indows 8N# applications can use ("/2based components known as #ctive< controls. 8espite being fairly complicated to create, huge numbers of these are available from third parties. /any containers capable of running #ctive< controls also e%ist, including !nternet E%plorer and the &indows shell. Civen this large installed base of both #ctive< controls and containers for those controls, there must be some way for &indows Forms controls to interoperate with this world. There is a way. To use an #ctive< control in a &indows Form environment, the #ctive< (ontrol !mporter, #%imp, can be used to create a wrapper for the control. #s with other parts of the .NET Framework's support for ("/ interoperability, this tool reads the #ctive< control's type library and produces an assembly containing analogous metadata. To allow a &indows Forms control to be used in a container that e%pects only #ctive< controls, the &indows Forms control can inherit from the class +ser(ontrol. This class implements everything re$uired to make the &indows Forms control look like an #ctive< control and thus be hostable in the many #ctive< control containers that e%ist today. #lso, because #ctive< controls are ("/2based, any &indows Forms control used in this way must have an entry in the &indows registry, 'ust as in the ("/ interoperability scenarios described earlier in this chapter.

/indows Forms controls can emulate Active) controls !n &indows 8N#, Gisual 6asic and (JJ had completely different approaches to building C+!s. 6ecause of this, #ctive< controls were based on ("/, which allowed them to work with both languages. The predictable result was comple%ity. &indows Forms sweeps away the accumulation of C+! technologies that have built up on the &indows platform, replacing them with a single consistent approach. &hile you may lament the effort re$uired to learn this new approach, there is certainly some appeal in finally having 'ust one way to build &indows user interfaces. /indows Forms provides a common mechanism for creating 78Is in any 1*.,based language

Você também pode gostar