Programming .NET With Visual
Programming .NET With Visual
NET
Contents
1. Introduction to .NET Framework
The Common Language Runtime, The Intermediate Language, Mixed Language Programming
Branching and Looping, Basic and User Defined Types, User Defined Methods. Classes and Namespaces, Interfaces and Delegates, Raising and Handling Events
14
Exposing assemblies and types, Dynamic instantiation and Invocations, Creating and Using Attributes
4. Reflection
33
5. Multithreading
Processes and Threads, Thread synchronization and Coordination, Asynchronous Programming Model Input and Output Streams, Object Serialization, Working with XML Documents.
40
6. Streams
49
7 Sockets
..
60
68
Accessing and Updating Data using ADO, Paramaterized SQL and Stored Procedures, Working with Disconnected Datasets. Windows Forms and Controls, Windows Forms and Data Access, Creating Custom Controls.
77
88
Web Forms and Server Controls, Web Forms and Data Access, Creating Web-Services.
97
Using Native Dlls and COM Components, Messaging with MSMQ, Creating Serviced Components with COM+.
112
-1-
1.2 The Intermidiate Language: Currently Microsoft provides compilers for C# (Pronounced as C Sharp), VisualBasic.NET, Managed C++ and JScript in their .NET Framework SDK. These compilers generate the so called Intermediate Language(IL) code which is then assembled to a Portable Executable(PE) code. The PE code is
Copyright 2001 K.M.Hussain <km@hussain.com> -2-
-5-
-6-
-7-
-9-
The Structure keyword is used to create a composite type called structure . In above example ClubMember is a structure with three fields Name, Age and Group. Note the Group field is of type MemberType and as such it can take only one of the four values defined in MemberType enum. The fields are declared Public so that they are accessible outside the scope of structure block. A structure is automatically instantiated when a variable of its type is declared. In above example variable a is declared to be of type ClubMember. Next the public fields of ClubMember is set for this instance. Note how Group field of a is set: a.Group = MemberType.Eagles A structure is a value type i.e when a variable holding an instance of a structure is assigned to another variable of same type, a new copy of the instance is created and assigned. Consider statement Dim b As ClubMember = a Here b contains a copy of a. Thus change in one of the fields of b does not affect fields of a. Thus output of program prints age of John as 13. In contrast the Class is a reference type. club2.vb is similar to club1.vb except now ClubMember is a class instead of structure Imports System Enum MemberType Lions Pythons Jackals Eagles End Enum Class ClubMember Public Name As String Public Age As Integer Public Group As MemberType End Class Module Test Sub Main() Unlike value type a reference type must be instantiated with new operator Dim a As New ClubMember() a.Name = "John"
Copyright 2001 K.M.Hussain <km@hussain.com> - 10 -
- 13 -
- 18 -
- 19 -
- 20 -
2.
3.
4.
5.
6.
- 23 -
- 25 -
- 29 -
- 30 -
- 32 -
- 33 -
End If lookup for a Execute method which takes no arguments Dim m As MethodInfo = t.GetMethod("Execute") obtain AuthorizeAttribute if supported by this method Dim auth As AuthorizeAttribute = CType(Attribute.GetCustomAttribute(m, _ GetType(AuthorizeAttribute)),AuthorizeAttribute) If Not auth Is Nothing Console.Write("Enter Password: ") If Not Console.ReadLine() = auth.Password Console.WriteLine("Password is incorrect") Exit Sub End If End If m.Invoke(Nothing, Nothing) Execute is a static method and takes no arg End Sub End Module Compile above program using command: vbc executer.vb execattr.vb Apps.vb provides few classes for testing executer program. Imports System <Executable> Public Class AClock Public Shared Sub Execute() Console.WriteLine("Its {0}", DateTime.Now) End Sub End Class <Executable> Public Class AGame <Authorize("tiger")> Public Shared Sub Execute() Dim r As Random = New Random() Dim p As Integer = r.Next(1,10) Console.Write("Guess a number between 1 and 10: ") Dim q As Integer = Int32.Parse(Console.ReadLine()) If p = q Then Console.WriteLine("You won!!!") Else Console.WriteLine("You lost, correct number was {0}",p) End If End Sub End Class Public Class AMessage Public Shared Sub Execute() Console.WriteLine("Hello World!") End Sub End Class
Copyright 2001 K.M.Hussain <km@hussain.com> - 38 -
- 39 -
We create a Thread instance by passing it an object of ThreadStart delegate which contains a reference to our SayHello method. When the thread is started (using its Start method) SayHello will be executed in an asynchronous manner. Compile and run the above program, you will notice series of Hello and Bye messages appearing on the screen. When the program is executed the CLR launches the main thread (the one which executes Main method) within the body of main we launch thread t (which executes SayHello method). While thread t goes in an infinite loop printing Hello on the console the main thread concurrently prints Bye on the console 10000 times, after which the main thread kills thread t invoking its Abort() method before it itself terminates. If thread t would not be aborted in this fashion it would continue to execute even after the main thread terminates. We could also mark thread t as Back Ground thread, in which case t would automatically abort soon after the last foreground thread (main thread in this case) would terminate. The program below (threadtest2.vb) shows how: Imports System Imports System.Threading Module ThreadTest2 Sub SayHello() Dim i As Integer = 1 Do Console.WriteLine("Hello {0}",i) i =i +1 Loop End Sub Sub Main() Dim t As Thread = New Thread(AddressOf SayHello) t.IsBackground = True t.Start() Dim i As Integer For i = 1 To 10000 Console.WriteLine("Bye {0}",i) Next End Sub End Module Just running threads simultaneously is not the whole thing, we sometimes need to control them In program below (sleepingthread.vb) the main thread prints Hello 15 times while at the same time another thread t prints Welcome 5 times followed by a Goodbye . The programs sees to it that the Goodbye message printed by thread t is always the last message of the program. To achieve this control thread t puts itself to
Copyright 2001 K.M.Hussain <km@hussain.com> - 41 -
- 44 -
- 47 -
- 48 -
- 52 -
Class authors need to be aware of serialization. The serialization services assume that a type is NOT Serializable unless type is specifically marked as Serializable (using System.IO.Serializable attribute). In the most simple case marking a class as Serializable is the all the class author will have to do. Given below (employee.vb) is the Employee class whose instance we will serialize. Imports System Imports System.Runtime.Serialization <Serializable> Public Class Employee Public Name As String Public Job As String Public Salary As Double Public Sub New(_name As String, _job As String, _salary As Double) Name = _name Job = _job Salary = _salary End Sub Public Sub New() End Sub We override ToString() method of System.Object. This method is invoked whenever an Employee object is to be converted to a string. Public Overrides Function ToString() As String ToString = String.Format("{0} is a {1} and earns {2}",Name,Job,Salary) End Function End Class The program below (binsertest1.vb) creates an instance of Employee class and stores it in file emp.bin. It also retreives and displays the object.
Copyright 2001 K.M.Hussain <km@hussain.com> - 53 -
- 54 -
- 59 -
Finally
Loop s.Close()
code in finally block is guranteed to execute irrespective of whether any exception occurs or does not occur in the try block client.Close()
1.3 Multicasting with UDP: Unlike TCP, UDP is connectionless i.e data can be send to multiple receivers using a single socket. Basic UDP operations are as follows: 1. Create a System.Net.Sockets.UdpClient either using a local port or remote host and remote port Dim client As New UdpClient(local_ port) or Dim client As New UdpClient(remote_host, remote_port) 2. Receive data using above UDPClient. Dim ep As System.Net.IPEndPoint Dim data As Byte() = client.Receive(ep) byte array data will contain the data that was received and ep will contain the address of the sender 3. Send data using above UdpClient.. If remote host name and port number has already been passed to UdpClient through its constructor then send byte array data using client.Send(data, data.Length) Otherwise send byte array data using IPEndPoint ep of the receiver client.Send(data, data.Length, ep) The program below (empudpserver.vb) receives name of an employee from a remote client and sends it back the job of that employee using UDP. Imports System Imports System.Text Imports System.IO Imports System.Net Imports System.Net.Sockets Imports System.Configuration Module EmployeeUDPServer
Copyright 2001 K.M.Hussain <km@hussain.com> - 64 -
UDP also supports multicasting i.e sending a single datagram to multiple receivers. To do so the sender send a packet to an IPAddress in range 224.0.0.1 239.255.255.255 (Class D address group). Multiple receivers can join the group of this address and receive the packet. Program below (stockpricemulticaster.vb) sends a datagram every 5 seconds containing share price (a randomly calculated value) of an imaginary company to address 230.0.0.1. Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Module StockPriceMulticaster Dim symbols As String()= {"ABCD","EFGH", "IJKL", "MNOP"} Sub Main() Dim publisher As New UdpClient("230.0.0.1",8899) Console.WriteLine("Publishing stock prices to 230.0.0.1:8899") Dim gen As New Random() Do Dim i As Integer = gen.Next(0,symbols.Length) Dim price As Double = 400*gen.NextDouble()+100 Dim msg As String = String.Format("{0} {1:#.00}",symbols(i),price) Dim sdata As byte() = Encoding.ASCII.GetBytes(msg) publisher.Send(sdata,sdata.Length) System.Threading.Thread.Sleep(5000) Loop End Sub End Module Compile and start stockpricemulticaster The next program (stockpricereceiver.vb) joins the group of address 230.0.0.1, receives 10 stock prices and then leaves the group. Imports System Imports System.Net Imports System.Net.Sockets Imports System.Text Module StockPriceReceiver Sub Main()
Copyright 2001 K.M.Hussain <km@hussain.com> - 66 -
- 67 -
- 69 -
- 75 -
- 76 -
The .NET Framework includes the OLE DB .NET Data Provider (System.Data.OleDb) and the SQL Server .NET Data Provider (System.Data.SqlClient) for Microsoft SQL Server 7.0 or later. To use the OLE DB .NET Data Provider, you must also use an OLE DB provider. The following providers are compatible with ADO.NET. Driver SQLOLEDB Provider Microsoft OLE DB Provider for SQL Server MSDAORA Microsoft OLE DB Provider for Oracle Microsoft.Jet.OLEDB.4.0 OLE DB Provider for Microsoft Jet
- 77 -
Try
A copy of data in a DataSet can be stored in the XML format using its WriteXml method. The program below (dstoxml.vb) stores all the records in the product table in prod.xml file. Imports System Imports System.Data Imports System.Data.SqlClient Module DataSetToXml Sub Main() Dim cn As New SqlConnection("server=localhost;uid=sa;pwd=;database=sales") Dim cmd As New SqlDataAdapter("select * from product",cn) Dim ds As New DataSet("products") cmd.Fill(ds,"product") ds.WriteXml("prod.xml") End Sub End Module The content of prod.xml generated by the above program is as follows: <?xml version="1.0" standalone="yes"?> <products> <product> <pno>101</pno> <price>350</price> </product> <product> <pno>102</pno> <price>975</price> </product> . </products> Content of a valid xml file can also be loaded in a DataSet for further processing. The next program (xmltods.vb) loads prod.xml in a DataSet and displays its records. Imports System Imports System.Data Imports System.Xml Module XmlToDataSet
Copyright 2001 K.M.Hussain <km@hussain.com> - 86 -
- 87 -
- 96 -
- 97 -
- 111 -
- 112 -
- 113 -
- 117 -
- 121 -