Creating Type-Safe And Reusable Code Using
Generics
Generics means parameterized types. They
enable you to create classes, interfaces, methods and delegates in which the
type of data operated on is specified as a parameter. Using generics, it is
possible to create a single class that works with different types of data.
Advantages of generics
Reusability
A single generic type
definition can be used for multiple scenarios in the same code, without any
alterations. For example, consider that you are writing code to add two
numbers. Prior to the concept of generics, the best way to handle this was to
create overloads of a method with different data types and return the value. However,
now you can create a generic method and call it with values of the required
data type.
Type safety
Generic data types
provide better type safety, especially in situations
where collections are
used. In a Collection class, when you add objects, the compiler does not check
the type of the object you are adding. As a result, the cast at run time may
fail. On the other hand, you can use generics to define the type of objects to
be passed to a collection and the compiler at compile time ensures that only
those objects are passed. This improves type safety and reduces the possibility
of type casting errors.
Performance
Generic types perform
better than normal system types because they
reduce the need for
boxing, unboxing, and type casting the variables or objects.
***GenericDemo1.cs***
Assigning Null Values To Value Types Using
Nullable Types
.NET 2.0 provides a
new feature called the Nullable data type that you can use to assign null
values for value type variables. A Nullable data type can store null values in addition
to the normal set of values. For eg, if you define a Nullable int data type, it
can store either a Null value or an integer value.
***NullableDemo.cs***
Implementing Collections And Generics
By using collections,
you can store several items within one object. Collections have methods that
you can use to add and remove items. These methods automatically resize the
corresponding data structures without requiring additional code.
Collections are
classes that are used to store arbitrary objects in a structured manner.
Non-Generic Collections
Can store multiple types
of objects in the collection simultaneously. Additionally, all objects are
stored as System.Object. When you retrieve an object from a non-generic
collection, you have to explicitly cast it to the type you want to work with.
Generic Collections
Are new in .NET 2.0.
When you create an instance of a generic collection, you determine and specify
the data type you want to store in that collection. Generic collections support
the storage of both value types and reference types. They are type-safe.
Collection Interfaces
A collection
interface is the backbone of a collection class because each interface allows
the collection class to support a different behavior. For eg, the IList
interface allows your collection to behave like a list and be indexed, and the
IDictionary interface allows your collection to behave like a dictionary where
items can be retrieved by a key. Every collection class, non-generic or
generic, implements at least one or more collection interfaces. The non-generic
version of collection interfaces is available in the System.Collections
namespace, and the generic version is available in the
System.Collections.Generic namespace.
·
IComparable
·
ICollection
·
IList
·
IComparer
·
IEqualityComparer
·
IDicitionary
·
IEnumerable
·
IEnumerator
Primary Collection
Types (NON-GENERIC)
1.
ArrayList
Class (System.Collections)
Represents a list, which is similar to a
single-dimensional
array that you can resize dynamically.
***Class1.cs***
2.
Stack
Class (System.Collections)
Follows the last-in,
first out (LIFO) principle, where elements are added to and removed from a
collection at the same end of the stack.
***Class2.cs***
3.
Queue
Class (System.Collections)
Follows the first-in, first-out (FIFO) principle, where
elements are added to a collection at one end of the
queue and removed from the other end.
***Class3.cs***
Iterating Through Elements of A Collection
Using Enumerators
You can provide the
iteration functionality for user-defined classes by implementing the
IEnumerable interface and overriding the GetEnumerator method. By implementing
this interface, you can iterate through the members of the class by using a
foreach loop. Prior to .NET 2.0, a class had to implement the IEnumerable
interface and then override the GetEnumerator method in order to support enumeration.
In .NET 2.0, C# language includes a new feature called iterators. Iterators are
the methods that allow you to support enumeration without having to implement
the IEnumerable interface. You apply iterators by using the yield statement.
Iterators allow you to create classes and treat those as enumerable types and
enumerable objects. This process is called implementing an enumerable pattern.
***Class4.cs***
How Reference Types Are Accessed Based On
Key/Value Pairs And Comparers
.NET provides the
dictionary-style lookup classes to help you sort objects on the basis of
name/value pairs. The Comparer, Hashtable, and SortedList classes are available
in the System.Collections namespace.
Comparer Class
Compares two objects
and determines whether they are less than, equal to, or greater than each
other. You can use this class to sort a collection. It is case-sensitive.
Compare method returns –1, 0, or 1 if
the objects compared
are less than, equal to, or greater than one another.
***Class5.cs***
Hashtable Class
Represents a
collection of name/value pairs that are organized on the
basis of the hash
code of the key being specified. With the Hashtable class, you can dynamically
add and remove elements without reindexing.
***Class6.cs***
SortedList Class
Represents a
collection of name/value pairs that are accessible either by a key or by an
index but are sorted only by keys. When you add an element to the SortedList
class, it is inserted in the correct sort order, and the indexing adjusts
accordingly.
***Class7.cs***
BitArray Class
A bit structure
represents a collection of binary bits—1s and 0s. These 1s and 0s are
represented as Boolean values, where a binary 1 is true and a binary 0 is
false. A bit structure is ideal in cases where you need to keep track of a
large number of items and the value of each item is binary. The size of a bit
structure in the memory depends on the number of elements in the collection.
***Class8.cs***
Generic Collections
Generic List Class
Provides methods to
search, sort, and manipulate the elements of
a generic list. The
generic List class can be considered similar to the generic version of the
ArrayList class. By using the generic List class, you can create a generic list
that behaves like an ArrayList. Unlike an ArrayList, however, the List class
can store either reference types or value types, while the ArrayList stores
only the System.Object type. This eliminates the need to box, unbox, and cast
the elements from a System.Object data type.
***Class9.cs***
Generic Stack and
Queue Classes
Stacks and queues
follow the FIFO or LIFO behavior.
***Class10.cs***
Generic Dictionary,
SortedList And SortedDictionary Classes
***Class11.cs***
***Class12.cs***
Generic LinkedList
Class
Allows you to define
nodes that have a common data type, each node pointing to the previous and
following nodes. A collection with this behavior is referred to as a doubly
linked list. With a strongly typed doubly linked list you can traverse forward
and backward through the nodes to reach a particular node. You can perform
several operations such as addition, deletion, and retrieval of elements from a
doubly linked list. You need to declare the data type of nodes while creating a
doubly linked list.
***Class13.cs***
Working With Specialized
Collections
You are developing an
application that uses collection classes. You find that the application is
unable to retrieve a specific object from a SortedList collection. You check
the SortedList and find it in order. However, you discover that while adding a
particular object to the collection, the key is specified as a lowercase
string, however, while retrieving the same object, the key is an uppercase
string. This problem would not have arisen if a SortedList could be case
insensitive. Moreover, because the collections in this application have keys as
strings, you need to create a generic List collection with the target type as
string to ensure that the collections provide type safety. Such requirements
are met by using the specialized collections available in the
System.Collections.Specialized namespace.
Specialized
collections are predefined collections that serve a special or highly specific
purpose.
Some Uses:
·
To implement a small
collection to store a maximum of 10 elements, by using key/value pairs similar
to the Hashtable class. You want the performance of this collection to be
extremely effective.
·
You want to implement
a type-safe ArrayList class for string values and also have the appropriate
enumerators for it. Another way of doing this is to use a generic collection
like the List class by specifying the associated type as string.
·
You want to create a
SortedList class that is not case-sensitive.
StringCollection
Class
Represents a
collection of strings and is a strongly typed version of the ArrayList class
for string elements.
***Class14.cs***
StringDictionary
Class
Implements a hash
table with the key and the value strongly typed to be strings rather than
objects. The key cannot be a null reference but the value can. The key is
handled in a case-insensitive manner; this means that it is translated to
lowercase before it is used with the string dictionary.
***Class15.cs***
CollectionsUtil Class
Provides static
methods for creating collections that ignore the case in strings. The methods
provided by the CollectionsUtil class create caseinsensitive instances of
Hashtable and SortedList classes. These methods generate a case-insensitive
instance of the collection by using case-insensitive implementations of the
hash code provider and the Comparer class. The resulting instance can be used
like any other instances of that class.
***Class16.cs***
ListDictionary Class
Is a simple
implementation of the IDictionary interface by using a singly linked list. It
is smaller and faster than the Hashtable class if the number of elements is 10
or fewer. Each element of the ListDictionary class is a key/value pair of the
type DictionaryEntry.
***Class17.cs***
HybridDictionary
Class
Uses the appropriate
implementation for a dictionary depending on the size of the collection. You
can use a HybridDictionary when you are uncertain about the number of items
that you will store in your collection. If you frequently store 10 elements or
less, you can use ListDictionary internally for their storage. If you store
more than 10 elements, you can use Hashtable to internally store these
elements. Therefore, you always use the most efficient storage mechanism by
using the HybridDictionary class.
***Class18.cs***
OrderedDictionary
Class
Represents a
collection of key/value pairs that are ordered on the basis of a key or an
index. Each element is a key/value pair stored in the DictionaryEntry object.
***Class19.cs***
Creating String-Based
Keys Using Specialized Classes
The
System.Collections.Specialized namespace in the .NET Framework provides various
named collection classes that help you create collections with string-based
keys.
These classes include
NameObjectCollectionBase,
NameObjectCollectionBase.KeysCollection, and NameValueCollection.
These classes provide
the abstract base class for a collection of associated string keys and object
values that can be accessed either by the key or by the index. These
collections are very useful when you are working with a collection of strings.
NameObjectCollectionBase
Class
Provides the abstract
base class for a collection of associated string keys and object values that
can be accessed by either the key or by the index. The underlying structure for
this class is a hash table.
NameObjectCollectionBase.KeysCollection
Class
Represents a
collection of the string keys of a collection. You can retrieve KeysCollection
of a particular NameObjectCollectionBase by using its Keys property.
KeysCollection contains the available string keys in a collection and you can
traverse through the keys by using the index for the keys or by retrieving the
enumerator for KeysCollection.
***Class20.cs***
NameValueCollection
Class
Represents a
collection of associated string keys and string values that can be accessed by
either the key or the index. This collection is based on the
NameObjectCollectionBase class.
When you add elements
to a NameValueCollection, the capacity is automatically increased as required
through reallocation.
***Class21.cs***
Creating Custom Collections Using
Collection Base Classes
Collection base
classes provide the abstract base class for strongly typed non-generic
collections. You can create custom or user-defined collections by using the two
types of collection base classes, CollectionBase and ReadOnlyCollectionBase.
Because these classes are abstract, you cannot create instances of these
classes.
You need to derive
your own classes from collection base classes. Custom or userdefined
collections derived from the CollectionBase class are modifiable. This means
that after creating these collections, you can add, remove, and change the
items they contain. In contrast, collections derived from the
ReadOnlyCollectionBase class are read-only. You cannot modify the objects
created from this class.
***Class22.cs***
Creating Custom Dictionary Types Using
Dictionary Base Types
Dictionary base types
provide the most convenient way to implement a custom dictionary type. The
implementing class just needs to provide methods and properties through which
the elements can be stored and accessed from the dictionary.
DictionaryBase Class
Provides the abstract
base class for a strongly typed collection of key/value pairs. Each element in
a DictionaryBase collection is of type
DictionaryEntry. You
can use the DictionaryBase class to implement a dictionary style lookup
collection, where a corresponding key refers to a corresponding object in the
collection.
***Class23.cs***
Reading And Writing Files
.NET 2.0 provides
classes to control every aspect of interaction between the application and the
file system. Application types ranging from Console applications to Web
applications and Windows applications can make use of the file system classes
to store, isolate, compress, and validate user-supplied data.
Managing The File System
The ability to save
and retrieve data requires interaction with the underlying file system of the
application. Interaction with the underlying environment is referred to as
input and output. .NET provides classes in the System.IO namespace to assist in
managing the underlying environment.
Accessing File Paths
Using The Path Class
Accesses each segment
of a file or directory path, including the drive letter, the directory name,
the file name, the file extension, and the path segment separator. In addition,
you can manipulate each segment of a file or directory path by using this
class.
You can specify paths
in 2 ways.
• Absolute
A path that fully
specifies all the segments of the file or
directory path from
the drive letter to the desired directory or
file name and
extension is referred to as an absolute path, for
example,
C:\Windows\System32.
• Relative
A path that specifies
only segments of a file or directory path
necessary to locate
the file or directory related to the current
file or directory is
referred to as a relative path, for example,
Windows\System32.
***Class24.cs***
Accessing Files Using
File and FileInfo Classes
A file is a container
for text. Although a file may contain text of only a single type at any given
time, the text may be in formats such as plain text, encrypted text, serialized
binary text, or Extended Markup Language (XML). Files may reside in any
directory in a file system.
The File class is a
static class that is used to work with a file. It is commonly used when only a
single operation is performed on a file. It performs security checks for each
method that is called on the
File class to ensure
that the user is granted permission to perform the action on the file. The File
class performs security checks for each method that is called on the File class
to ensure that the user is granted permission to perform the action on the
file.
The FileInfo(extends
FileSystemInfo class) class is an instance class commonly used to perform
multiple operations on a file. In contrast to the File class, the FileInfo
class only performs a security check for the user after the class is
instantiated.
***Class25.cs***
Accessing Directories
Using Directory And DirectoryInfo Classes
A directory is a
location for storing files and other directories in a directory tree structure.
You organize the files into directories. All directories reside on a drive and
each directory may or may not contain subdirectories.
.NET provides 2
classes, Directory and DirectoryInfo, in the System.IO namespace for directly
working with the directories. The Directory and DirectoryInfo classes function
in a similar manner as the File and FileInfo classes with the exception that
the Directory and DirectoryInfo classes apply to directories instead of files. This
is because the DirectoryInfo class, like the FileInfo class, also extends the
FileSystemInfo class.
***Class26.cs***
Accessing Drives
Using The DriveInfo Class
A drive is a
partition on a physical hard disk, which is used to store information in a computer.
Drives are represented by letters A, B, C, and D that typically represent
floppy disk drives, local hard disk drives, and local CD-ROM/DVD-ROM drives.
.NET Framework
provides the DriveInfo class and the DriveType enumeration for directly working
with the drives.
The DriveInfo class
is an instance class that extends the FileSystemInfo class and is used to work
with a drive. You can query an instance of the DriveInfo class to determine
information about the drive, such as the drive letter, the type of drive, and
the amount of free space on the drive.
The DriveType
enumeration is a helper enumeration for the DriveInfo class used to determine
the type of drive represented by an instance of the DriveInfo class.
***Class27.cs***
The FileSystemWatcher
Class
You use the
FileSystemWatcher class to monitor the current directory and its subdirectories
for changes in the directories or files contained in the directory. The events
commonly monitored by the FileSystemWatcher class include Changed, Created, Deleted,
Error, and Renamed. Each of these events can apply to a file or a directory.
The FileSystemWatcher
class uses a buffer to store event notifications until it can address them.
Windows notifies the FileSystemWatcher class of events by adding event notifications
to the buffer. This buffer is similar to an array and is fixed in size.
If many events occur
simultaneously, the buffer may overflow and stop recording detailed event
notifications.
To prevent a buffer
overflow, you can increase the initial size of the buffer using the
InternalBufferSize property. However, this consumes memory resources. You can
also prevent a buffer overflow by using the NotifyFilter and
IncludeSubdirectories properties by creating a filter so that only particular
files and directories are monitored.
Handling File System Events Using
FileSystemWatcher Class
The following are the
event handler delegates of the FileSystemWatcher class.
• ErrorEventHandler
Indicates the method
that will be called if an error occurs.
• RenamedEventHandler
Indicates the method
that will be called if a file or directory
being monitored by an
instance of the FileSystemWatcher class
is renamed.
***Class28.cs***
Working With Byte
Streams
A stream is used to
bridge the gap between your application and a file so that you can store and
retrieve data from a file.
.NET provides stream
classes in the System.IO namespace to assist reading data from and writing data
to files and memory.
A stream serves as a
conduit between application code and a data backing store. A data backing store
may include a database, file, memory, or any other entity capable of persisting
data. A file represents a single type of data backing store because it is a
container for text, binary, or image data.
The process of moving
bytes of data through a conduit and between endpoints is called streaming. You
cannot pass data directly between these endpoints. Therefore, a stream is used
to connect the two endpoints while storing or retrieving data. For example, a
stream connects an endpoint, such as the application code, to another endpoint,
such as a file.
For eg, media and
other content can be streamed in a Web environment when a media player, such as
Windows Media Player is connected to a media source and bytes of data are retrieved
for playback.
The Stream Class
The Stream class is
an abstract class that provides the base functionality for all streaming
classes in .NET.
A stream represents
stream of bytes of data.
A stream performs the
following three primary tasks:
Reading
Is the process of
reading a series of bytes from a data source. by using a stream.
Writing
Is the process of
writing a series of bytes to a data source by using a stream. Most streams
support the ability to maintain a pointer within the series of bytes contained
in the stream as well as the ability to move the pointer within the stream.
Seeking
Is the process of
maintaining and manipulating a location pointer within a stream.
Managing File Data
Using The FileStream Class
Is a concrete class
that extends the Stream class and is used to stream data to and from a file.
***Class29.cs***
Managing Memory Data Using The
MemoryStream Class
Is a concrete class.
It extends the Stream class and is used to stream data to and from application
memory.
The data stored in
memory does not persist because when you shut down an application, the data in
the memory is deleted. Therefore, for the data to persist, you need to store it
in a file.
The MemoryStream
class provides a performance benefit. Reading data from and writing data to
memory results in better performance than reading from and writing to a
file. If the data is used temporarily as working data, it should be stored in
memory instead of a file.
***Class30.cs***
Improving Stream Performance Using The
BufferedStream Class
Is a concrete class
that extends the Stream class and is used to provide an additional memory
buffer to another type of stream. This class must be configured to either read
or write when an instance of the class is created, but it cannot be configured
to perform both the tasks at the same time.
Applying the
BufferedStream class to an existing .NET stream results in a double buffer.
The most common
application of the BufferedStream class is in custom stream classes that do not
include a built-in buffer.
***Class31.cs***
Compressing and Protecting Stream
Information
To reduce the amount
of space that the stream uses, you can
compress a stream before saving or transferring it and then decompress
the stream before using it. During compression, the bytes in a file are first
converted into a stream and then the stream is
compressed. While the
stream is being compressed, insignificant bytes of data are removed from the
byte stream.
While removing the insignificant bytes of data, a map is
created so that the bytes removed during compression can be replaced during
decompression, and the format of the bytes is converted to a more compact
format.
Compression is the process of making a file smaller by
encoding the information by using fewer bits. Decompression is the process of
using the map that was created during compression to restore a compressed file
to its original state and size.
Compressing Information Using the DeflateStream Class
The
DeflateStream class provides methods for compressing and decompressing streams
by using the Deflate algorithm. The Deflate algorithm is an industry-standard
algorithm for lossless file compression and decompression. Lossless file
compression allows the
reconstruction
of the exact data from the compressed data. You cannot use the DeflateStream
class to compress files larger than 4 GB.
***Class32.cs***
Compressing Stream Information
Using The GZipStream Class
To check
for errors that occur during compression or share compressed data with programs
written for other operating systems, you should use the GZipStream class
instead of the DeflateStream class.
The
GZipStream class contains methods to compress and decompress files by using the
GZip data format. Files that are compressed by using the GZipStream format are
saved with the extension gz. The GZip utility is often used by other operating
systems. You cannot use the GZipStream class to decompress files larger than 4
GB.
The
GZipStream class uses the same algorithm as the DeflateStream class, but you
can extend it to use other compression formats. The GZipStream class is a
wrapper around the DeflateStream class that includes a header, a body, and a
footer. The compressed data is stored in the body and the information in the
header and footer allows the GZipStream class to check for errors that occur
during the compression process. ***Class33.cs***
Isolated
Storage
Isolated
store is a unique data compartment that helps store data of an application.
This allows the application to protect its data from other applications.
Isolated
storage allows an application to protect its data from other applications. It
also allows the application to save the data without using a hard-coded path to
the file.
Isolated
storage enables you to store data in a unique data compartment called a store.
An isolated store can be associated with an application, an assembly, a domain,
a user, or any combination of these items.
In
addition, you can associate an isolated store with a roaming profile of a user
so that the data is available wherever the user uses the application. When you
use isolated storage, the location of the data is transparent to you because
the data compartment is an abstraction rather than a physical location.
You cannot
determine the fully qualified path to the isolated storage files that the
application saves because isolated storage uses cryptographically strong names
for directories.
The
IsolatedStorageFile and IsolatedStorageStream classes allow a .NET application
to save data locally by using isolated storage.
The
IsolatedStorageFile class represents an isolated storage area or isolated
store, which contains files and directories. The IsolatedStorageFile class
represents an isolated store and not a file. The isolated store is assigned to
an assembly, and it helps you read and write data without hard-coding the
location of the file in the application code.
The
IsolatedStorageFileStream class exposes a file within the isolated storage. The
IsolatedStorageFileStream class works with the IsolatedStorageFile class to
read, write, and create files in isolated storage.
You can
create an isolated store that is scoped to the machine or to the user. Within
that scope, you can then associate the isolated store with an application,
assembly, or a domain. ***Class34.cs***
Managing
Application Data
What Is Text, Stream, String And
Binary Data?
Text
Represents
character data stored in a data backing store, such as a text file or a text
column. You can read text from a data backing store by using the TextReader class
and write text to the data backing store by using the TextWriter class.
Stream
A stream is a conduit for reading bytes from and writing
bytes to a data backing store. .NET provides the StreamReader and StreamWriter
classes to read and write text to a file. Both of these classes read and write
characters based on a particular character-encoding configuration. In addition
NET provides 3 Stream classes, FileStream, MemoryStream, and BufferedStream
that are used to read and write bytes.
String
A string is an array of characters stored in memory. In
.NET, a string is represented by the System.String class. It is represented as
String in VB.NET and string in C#.
Binary
A binary file is a file that is encoded in a binary format
and the data is stored as a series of bytes. Binary files can contain images,
sounds, text, or compiled code. The BinaryReader and BinaryWriter classes are
designed for reading and writing binary files.
Text And String Classes
TextReader Class
Is used to
read a sequential series of characters. The StringReader, StreamReader, and
BinaryReader classes inherit from the TextReader class.
TextWriter Class
Is used to
write a sequential series of characters. The StringWriter, StreamWriter and
BinaryWriter classes inherit from the TextWriter class.
Managing Strings
You can use the StringReader and StringWriter classes to
read and write strings to strings.
StringReader
class can extract each line from a long string that contains multiple lines.
The
StringWriter class stores its information in a StringBuilder. You can use the
StringBuilder class to manipulate strings.
Managing Streams Using
StreamReader And StreamWriter Classes
The StreamReader and StreamWriter classes are inherited
from the TextReader and TextWriter classes. You can use the StreamReader class
to read data from a stream and the StreamWriter class to write data to a
stream.
***Class35.cs***
Managing Binary Data Using
BinaryReader And BinaryWriter Classes
Are used to
read and write data in binary files, respectively. These classes read and write
primitive data types as binary values. These classes are used to read and write
binary files that can be shared with applications that process binary data.
***Class36.cs***
Manipulating
Strings
In .NET, a
string is an array of characters of the Char data type. Consequently, a string
is immutable because it is a reference type and does not hold its data
directly. This means that after you assign a value to an object, you cannot
change it. If you change the value of a string, a new string is created, and
the variable points to the new string.
StringBuilder
Class
To modify a
string repeatedly without incurring the overhead of creating a new object every
time you change the value of a string, you can use the StringBuilder class
rather than working directly with a string.
The
StringBuilder class represents a mutable string of characters.
***Class37.cs***
==========================================
Serializing
Data
.NET 2.0
provides built-in classes to convert data to formats that are portable, or easy
to transport to another location. This process of converting data into a
portable format is called serialization. The process of restoring the object or
data to its original state is called deserialization.
To store the
application data in a location such as a database or a file, you need to
convert it to a common format, such as a series of bytes. The process of converting
objects and data into a common format for storage or transportation is called serialization.
The most
common format in which objects and data can be serialized when storing or
passing them between threads or application domains is the binary format. These
application domains may reside on the same computer or in a controlled
environment such as a network. The binary format is a series of bytes that
represent the original state of the serialized object or data. At times, you
may need to transfer data between applications that reside in completely
different environments. In this situation, you can pass serialized objects and
data between applications by using the Web. When passing an object or data over
the Internet, the object must be serialized to a suitable format.
Serializing
Objects Using BinaryFormatter And SoapFormatter
To
determine the serialization format for objects, you need to use a formatter. A formatter
is required to indicate how you want to format the data that you are going to save
for deserialization.
BinaryFormatter
class generates a compact stream when you serialize an object. So it is useful
for storage and socket-based network streams. Serializes all the members of an
object, such as properties and enumerations, including the private members.
This allows BinaryFormatter to store all state data.
SoapFormatter
class generates a stream in SOAP format when you serialize an object. SOAP is a
specialized XML grammar intended for easy transport of data over the Web. You use
this class for serialization in applications spanning heterogeneous environments.
It is generally used for cross-platform interoperability. Serializes only those
members of an object that are declared marked with the Serializable attribute. Serializes only the
publicly declared members of an object.
***BinarySerializationDemo.cs***
***SoapSerializationDemo.cs***
Generating
Serialized XML Formats
The
SoapFormatter class serializes and deserializes objects into the SOAP format
according to the World Wide Web Consortium (W3C) SOAP specifications. In
addition, the SoapFormatter class produces entire SOAP messages with tags, such
as header, and provides limited options to customize the generated format. The
XmlSerializer class serializes and deserializes objects into and from XML
documents. Unlike the SoapFormatter class, you can control how objects are
encoded into the XML format by using the XmlSerializer class.
XML is an
open standard and an XML stream can be processed by any application regardless
of the platform. XML serialization is the process of converting the public properties
and fields of an object to a serialized XML format for storage or transport purpose.
XML serialization can also be used to serialize objects into XML streams
that
conform to the SOAP specification.
By default,
the XmlSerializer class maps each field and property of the object to be serialized
to an XML element with the same name. This implies that the resulting XML, created
by serializing a specific object, will possess separate elements to represent
the members of the corresponding class with the same naming convention defined
for these members in that class. By using the this class, you can customize the
XML format of the object being serialized, rather than depending on the default
mapping between the XML elements and the members of the class.
XML
Serialization Attributes
Customize how
XmlSerializer maps a class, field, or property to an XML document and declare types
that are not explicitly referenced in a source file. As a result, they
determine the resulting XML format for each class member associated with an attribute.
You can
apply these XML serialization attributes to classes and class members to
control the way in which XmlSerializer serializes or deserializes an instance
of the class.
***XmlSerializationDemo.cs***
Handling XML Serialization
Events Using Delegates
XML
serialization delegates represent methods that can handle different events of
an XmlSerializer class, such as the event raised when an unknown node, element,
or attribute is found in the serialized stream during deserialization.
***Class39.cs***
==========================================
Implementing Delegates And Events
Delegates,
like classes and interfaces, are reference types. You can declare a delegate type,
define a variable of a delegate type, and create an instance of a delegate.
Delegates are used to indirectly call one or more methods at run time. You do
not specify the method that will be invoked when you declare the delegate type
or a variable based on the delegate type. You specify the method that will be
called when you create an instance of the delegate, and you can dynamically
associate one or more instances with the variable at run time. You can use
delegates to call a method indirectly. They are similar to function pointers in
C++. However, unlike C++ function pointers, they are type safe and are
instances of objects with their own properties and methods.
By using
delegates, you can separate the invocation of a method from its definition.
This makes it possible to change what a method does as the state of a program
changes. By referencing a method as a delegate, you can also treat the method
as an object. You can use the delegate to pass the method as a parameter in a
different method invocation. You can also add multiple method references to the
invocation list of a delegate. Then, when the delegate is invoked, you can call
all the referenced methods.
Uses Of Delegates
Create
events
All events
in the .NET are based on delegate types.
Create
asynchronous method calls
Callbacks
in .NET 2.0 are based on delegate types.
Implement
polymorphic behavior
If you have
two objects that have similar methods with identical method signatures, you can
use the same delegate to invoke them. These objects need not be related by
inheritance and need not have a common interface. Moreover, the methods within
these objects can have entirely different names.
Use
generics in delegate signatures
By using
generics, you can instantiate a stronglytyped delegate that can be used at run
time with type safety without specifying a particular type in the signature of your
delegate type declaration. This helps you create an event in a generic class
and specify the return type and parameter types when you create an instance of
the delegate.
Types Of Delegates
Singlecast
When a
delegate references only a single method, it is called a singlecast delegate.
Multicast
A delegate
referencing more than one method is called a multicast delegate. As references
to additional methods are added to the delegate, they are stored in the invocation
list of the delegate. All delegates are implicitly multicast delegates.
YOU CAN USE
THE DELEGATE CLASS TO INSTANTIATE OBJECTS THAT CAN ACT AS A REFERENCE TO A SUBROUTINE,
A FUNCTION, A STATIC METHOD, OR AN INSTANCE METHOD.
WHEN YOU
DECLARE A DELEGATE, YOU MUST SPECIFY A METHOD SIGNATURE IN ADDITION TO THE RETURN
VALUE. WHEN YOU INSTANTIATE THE DELEGATE, YOU NEED TO REFERENCE THE METHOD THAT
WILL BE INVOKED. THIS METHOD MUST HAVE THE SAME METHOD SIGNATURE AS THE
DELEGATE, AND THIS METHOD MUST RETURN A VALUE AS DEFINED BY THE DELEGATE DECLARATION.
Using Delegates
By Using A Callback Pattern
This
example creates a ReportPrinter class that is used to print multiple reports
from an application. As the application needs feedback from the ReportPrinter
class, it creates a method that can be called back from the ReportPrinter class.
***CallbackDelegateDemo.cs***
New
Techniques In C# 2.0 To Enhance Delegate Behavior
Anonymous Methods
Anonymous
methods allow you to create an instance of a delegate by specifying a block of
inline code to be invoked by the delegate rather than specifying an existing
method to be invoked by the delegate. This allows you to conserve code because
you do not need to create a new method every time a delegate is passed as a
parameter to a method call.
***AnonymousMethodDemo.cs***
Covariance
Occurs when
the return type of the method referenced by the delegate inherits from the
return type of the delegate itself. Because the method’s return type inherits
from the delegate’s return type, the signatures are still considered a match.
***CovarianceDemo***
Contravariance
Contravariance
permits the declaration of a delegate with parameters that inherit from the types
used in the parameters of the method that will be invoked. However, for contravariance
to work, the order and number of parameters in the signatures of the delegate
as well as the method must still match.
***ContravarianceDemo***
Controlling Interaction Between
Components Using Events
Events are
a way for one class to notify another when something of interest happens. This is
the foundation of event-driven programming. While creating the class that is
notified, you can add an event handler for the event if you want to take some
action as a result of occurrence of the event. By using events, you can develop
classes independently of each other and still make them interact with each
other at run time.
How Events Work
Events are
designed based on the publisher or subscriber model.
Publisher
The class
that raises the event instantiates a delegate to be invoked when the event is raised.
This class is known as a publisher. By using a delegate, the publisher can
invoke one or more methods in the subscriber without determining the details of
the methods.
Subscriber
The class
that responds to the event adds one or more of its own methods to the publisher’s
delegate. This class is known as a subscriber. When the publisher invokes the delegate,
the subscriber’s methods are also invoked. The subscriber can specify zero,
one, or many methods to respond to the publisher’s event, without needing to
determine the details of how the event is raised.
Events, by
their very nature, are one-way operations and do not have a return value; so,
the subscriber does not need to consider the return value signature of the
event.
Creating And
Using Custom Events
·
Declare the
event in your class and identify the delegate and arguments that will be used.
·
Declare a
delegate that will be used to refer to the method or methods that will be called
when you raise the event.
·
Design a
class that will be used as an event argument to pass information to the called
methods when you raise the event.
IN C#, YOU
ALWAYS DECLARE EVENTS BY USING A DELEGATE SIGNATURE, BUT YOU CAN USE A PREDEFINED
DELEGATE, SUCH AS EVENTHANDLER, OR A CUSTOM DELEGATE WITH A SPECIFIC SIGNATURE.
***EventDemo1.cs***
Using The EventArgs Class To
Pass Arguments To An EventHandler
You can
pass arguments to a method handling an event by using a class that inherits
from the EventArgs class. In other words, whenever you want to pass a specific
piece of data from an event publisher to a subscriber method, you need to use a
custom class that inherits from the base EventArgs class.
You can
create event handlers with the parameters you like, but it is a good practice
to standardize on a signature that uses two parameters, an object parameter and
a parameter that inherits from EventArgs. You will use the object parameter to
pass a reference to the object that raised the event and the second parameter
to pass data to the method that handles the event.
***EventDemo2.cs***
Configuring And Installing Assemblies
All the
programs that you create in .NET are compiled as intermediate executable files
called assemblies. An assembly is a self-contained unit of code that contains
all the security, versioning, and dependency information and types and
resources that are built to work together and form a logical unit of
functionality.
By using
assemblies, you can also counter the limitations of COM objects, such as the
dependency of COM applications on registry settings. Assemblies resolve the
versioning conflicts that arise among different versions of applications.
Assemblies are portable and self dependent.
Difference Between
.dll And .exe Files
Additional
information about the.dll and .exe files is known as the metadata. The metadata
is commonly stored in a separate file called a type library or a .tlb file.
Benefits Of
Assemblies Over COM Components
Versioning
With
assemblies, you can install and run multiple versions of the application
simultaneously on the same machine, which is not possible with COM. If you
install a brand new COM component or another version of the same COM component,
it would normally overwrite the pre-existing version. This limitation of COM
components has led to other problems. You can rectify this situation by having multiple
versions of assemblies installed simultaneously on the same machine.
Portability
You can run
assemblies on multiple platforms. However, COM can only run on the Windows
platform. Assemblies are compiled to Microsoft Intermediate Language or IL.
This IL can then be ported to other platforms. In that format, it is known as a
portable executable file or a PE file. A version of the common language runtime
(CLR) that exists on the destination platform loads your MSIL. Using JIT
compilers, the CLR compiles the MSIL to machine language for that particular
environment.
Self-Dependency
Assemblies
are self-dependent and do not require an external type library file. A section
inside the assembly, known as the Manifest, contains the metadata, which stores
information similar to that stored in type libraries.
IL
Disassembler
.NET
provides a command-line utility known as the IL Disassembler that enables you
to look at the internal structure of an assembly. You can look at the contents
in the manifest, how IL is structured, and how it is created and rendered from
your search code after compilation occurs.
Forms Of Assemblies
Methods To Create
Assemblies
·
Visual
Studio Command Prompt
csc <filename>.cs
·
Visual
Studio IDE
After creating a project in the IDE, use the Build command on
the toolbar to create an assembly.
Single And
Multi-File Assemblies
If an
assembly is composed of a single *.dll or *.exe module, it is a single-file
assembly. They contain all the necessary MSIL, metadata and associated manifest
in an autonomous, single well-defined package.
Multi-file
assemblies are composed of numerous .NET binaries, each of which is termed as a
module. When building a multi-file assembly, one of these modules (primary
module) must contain the assembly manifest. The other related modules contain a
module-level manifest, MSIL and type metadata.
MULTI-FILE
ASSEMBLIES ARE USED IF YOU NEED TO CREATE A CLASS LIBRARY WRITTEN IN DIFFERENT
LANGUAGES AND WANT YOUR CLIENTS TO ONLY HAVE TO REFERENCE ONE ASSEMBLY.
Steps To
Create A Multi-File Assembly
***To be generated***
Forms Of Assemblies
On the
basis of sharing, assemblies can be categorized into 2 types:
Private
Assembly
An assembly
that is deployed with an application and is available
for use
only within that application is known as a private assembly. When you compile a
code module in .NET, a private assembly is created in the application’s folder,
by default.
Shared
Assembly
An assembly
that is installed in the GAC to be used by different applications is known as a
shared assembly. The GAC maintains different versions of an assembly that you
can use with different applications. You can also maintain multiple copies of
an assembly with the same name in the GAC, with different version information. .NET
provides gacutil.exe to install and uninstall shared assemblies to and from the
GAC.
The Global Assembly
Cache (GAC) (C:\<windows folder>\assembly)
is a
system-wide code cache managed by the CLR. Any assembly that needs to be shared
among other applications is typically installed in the global assembly cache.
The global assembly cache acts as a central repository for registering
assemblies. There are many advantages to installing the shared assembly in the GAC.
For eg, the GAC provides its own management tools, such as integrity checks,
for an assembly when it’s added to the GAC. These checks ensure that an
assembly is not tampered with, for eg, when a file has changed but the manifest
does not reflect the change.
Assigning A
Strong Name To An Assembly
A strong
name provides a unique identity to an assembly. This prevents naming and versioning
conflicts among assemblies and also ensures the authenticity of the assembly. Moreover,
you can install only strongly-named assemblies in the global assembly cache. It
is possible to have multiple copies of the same assembly in the global assembly
cache and yet there will be no conflict as long as their strong names are
different. Assigning strong names to assemblies allows multiple copies of an
assembly with different versions run at the same time on the same computer.
This is known as side-by-side execution.
Information
Contained In Strong Names
·
The textual
name of the assembly such as System.Data.
·
A version
number.
·
A public
key, such as, ab8734e01c1520ac and a digital signature that ensures the authenticity
of an assembly. Such information allows .NET to check whether the referenced
assembly is a genuine assembly or a malicious one by comparing its signature
with the one stored in the manifest file of its calling assembly.
·
Culture
information.
YOU CAN USE
sn.exe PROVIDED BY .NET TO CREATE AND ASSIGN A STRONG NAME TO AN ASSEMBLY.
Deploying An
Assembly Into The GAC
There are
various benefits of deploying an assembly in the GAC:
1.
It enables
different applications to reference an assembly from the same location.
2.
It helps
you secure the assembly from unauthorized access because the GAC folder can
only be accessed by the administrator or authorized users.
3.
It enables
you to store multiple versions of the same assembly.
Assembly Deployment
Methods
Installing An Assembly Using Installation
Types
.NET
includes classes that provide the flexibility to control the installation
process of an application through custom installers. You can also use these classes
to perform event-specific tasks during the installation process. For eg, if you
want to install an application based on the number of copies purchased by a
certain client, you need to perform certain validation tasks during the
installation process. These tasks include the online validation of the client
license, the number of copies purchased by the client, and the number of
instances already installed by the client. To perform these custom tasks, you
need a custom installer.
The
installer can also ensure that the installation takes place only when the
client computer is connected to the Internet and submits an installation
summary to a remote online server after every installation or whenever an
instance of the application is uninstalled. The custom installer also rolls
back changes made to the client computer if an error occurs during
installation. A custom installer can also install the database along with the
executable files and resources required by the application.
How Assembly
Installers Are Created
You can
create installers either by using VS.NET or programmatically by using the command
prompt window.
Visual
Studio
Allows you
to create four types of assembly installers:
1.
Setup project
Creates the
assembly installer for Windows-based programs
that are
installed on target systems. This project combines all
the
elements required to install the assembly into a package
with a
Setup.exe file. You can use this file to install the
assembly in
a private assembly folder or the GAC.
2.
Web Setup project
Creates the
assembly installer for Web-based programs. This
project
creates a setup program that installs files in a virtual
folder on a
Web server.
3.
Merge Module project
Creates an
installation package of the assemblies that can be shared by multiple
applications. You cannot deploy a Merge Module project independently.
4.
CAB project
Creates a
setup file that is small in size. A CAB project helps you compress the assembly
installers.
Command
Prompt
Enables
more flexibility in customizing your assembly installers. It also gives you
more control over handling errors at the time of installation.
Creating Custom Installation
Applications Using The Installer Class
Sometimes
you need to carry out more advanced actions during an installation process than
the ones that standard setup projects offer. Such types of actions during an installation
process are called as custom actions and can be implemented by using custom installer
classes.
.NET
provides the Installer class as a base class to create custom installer
classes. You can override the methods of the Installer class to perform
specific tasks that meet your requirements. The Installer class is a member of
the System.Configuration.Install namespace.
Steps To Create
A Custom Installer Class
1.
Create a
class that is inherited from the Installer class.
2.
Implement
overrides for the Install, Commit, Rollback, and Uninstall methods.
3.
Add the RunInstallerAttribute
to the derived class and set it to true. (if not done, the custom installer
classes or custom actions will not be invoked during the installation process.)
4.
Invoke the
installer.
Creating Globalized
Applications
Globalization
in terms of software design refers to designing a software application in a
neutral way. This means that the content that relates to a specific language
and culture is separated from the source code. By doing this, you can later
localize the application without modifying the source code of the software
program.
Localizing
an application involves supplying the various resources required for your application
and displaying everything in the user interface in the localized language. This
process is called localization. Resources such as text strings are localized.
You can design the bitmaps according to regional conventions to deliver the
original application experience in the selected culture and language. When
localizing an application, you need to consider the different formats and
cultural symbols of the target market.
.NET 2.0
provides various classes that help create global applications. These classes
belong to the System.Globalization namespace.
The process
of creating a globalized business application in .NET is normally broken down into
the processes of globalization, localizability, and localization.
Globalization
Globalization
is the process of designing your application so that it is able to detect when different
cultures are making requests of it. The process of globalization is preparing
and designing application so it’s capable of detecting and responding correctly
to the various cultures and locales in which it is used.
Localizability
Localizability
is the process of preparing an application for globalization. Localizability is
an analysis where you identify issues in the application that could hamper localization.
Once an application has been through the process of localizability and is ready
to be globalized, the application has two primary blocks, a data block and a
code block. The data block is locale specific resources and the code block is
the code that is applicable to any culture which makes requests for your
application. Code block is any type of code that replies to anything. Data
block is locale specific information resources.
Localization
Localization
is the process of going through and creating localized resources. Localized
resources are strings and data which appear in the language for a particular culture
or locale. Globalized apps do not have to be localized. You may have globalized
applications which do not localize but you can never have a localized
application without it being globalized.
Culture
A culture
is a combination of a country and a language code, which allows you to identify
a specific country and language combination. Every culture has some particular things
which are special to that culture. There are typically different calendar
settings, date-time settings, casings, and indexing orders that will be used
for ordering information. You can also have string formats, which are different
for culture as well.
Each
culture is identified using an industry-standard code. This code takes the form
of two pieces—two segments. The first segment of the code is going to consist
of two lowercase characters. The two lowercase characters are used to identify
the language. The two lowercase characters typically have a dash and after the
dash you have two uppercase characters. The two uppercase characters will be
representing the country for which you are representing as well.
Accessing Culture Information Using
CultureInfo Class
Its is used
to create global applications. The combination of each language and region is
represented by a new instance of this class, initialized with the desired
culture code. The CultureInfo class provides various properties and methods
that you can use to format display values.
***Class40.cs***
Accessing Region Information Using
RegionInfo Class
The
RegionInfo class is used for creating globalized applications. This class
represents specific country formats defined in the Windows operating system,
along with any customization that you make to the region through the Regional
and Language Options in Control Panel in
Windows.
The
RegionInfo class provides a number of properties that return the correct format
for the specified region. By using the RegionInfo class, you can retrieve
different facts about the region that you are targeting.
***Class41.cs***
Formatting Date/Time Values In A Culture
Using DateTimeFormatInfo Class
The
DateTimeFormatInfo class in the System.Globalization namespace helps you manipulate
date/time values and format them accordingly to the selected CultureInfo region.
An object of the
DateTimeFormatInfo class holds information on how to format and use date/time
values in different regions. You can inspect this information directly by
calling the properties and methods inside this class.
***Class42.cs***
Formatting Numeric Values Using
NumberFormatInfo Class
This class helps to
format numeric values, such as currency values, in particular string formats,
depending on the culture. You can use this class when you want to display numeric
values to the user by following regional conventions.
You can specify the
format values by using the NumberStyles enumeration. You can combine multiple
individual enumeration values to instruct the Parse() method of the integer
type on how you want to handle the string by using the NumberStyles enumeration.
When you call the
Parse() method on a type, such as an integer, the Parse method helps you to
input how you want to parse the corresponding string into an integer.
***Class43.cs***
Comparing Culture Information Using
CompareInfo Class
It is used to perform
string comparisons that follow regional order. You need to use an object of the
CultureInfo class and retrieve the CompareInfo property. By retrieving
CompareInfo from an object of the CultureInfo class that represents the desired
culture, you can perform string comparisons by using the methods of the
CompareInfo class. You can use the CompareInfo class in any method that expects
the IComparable interface because CompareInfo implements IComparable,
especially to perform sorting operations.
***Class44.cs***
No comments:
Post a Comment