Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# and the NET Platform, Second Edition - Andrew Troelsen.pdf
Скачиваний:
67
Добавлен:
24.05.2014
Размер:
22.43 Mб
Скачать
Part Two - The C# Programming Language

Summary C# and the .NET Platform, Second Edition

by Andrew Troelsen ISBN:1590590554

If you are a COM programmer by trade, this chapter must have given you warm fuzzies. The interface is a

Apress © 2003 (1200 pages)

collection of abstract members that may be implemented by a given class. Because an interface does not

This comprehensive text starts with a brief overview of the

supply any implementationC# languagedetails,and thenit isquicklycommonmovesto regardto keyantechnicalinterfaceandas a behavior that may be supported by a givenarchitecturaltype. Whenissuestwoforor.NETmoredevelopclassesrsimplement. the same interface, you are able to treat each type the same way (aka interface-based polymorphism).

TableC# providesof Contentsthe interface keyword to allow you to define a new interface. As you have seen, a type can C#supportand theas.NETmanyPlatform,interfacesSecondas necessaryEdition using a comma-delimited list. Furthermore, it is permissible to

build interfaces that derive from multiple base interfaces.

Introduction

Part One - Introducing C# and the .NET Platform

In addition to building your custom interfaces, the .NET libraries define a number of standard (i.e.,

Chapter 1 - The Philosophy of .NET

framework-supplied) interfaces. This chapter focused on the interfaces defined within the

Chapter 2 - Building C# Applications

System.Collections namespace. As you have seen, you are free to build custom types that implement

these predefined interfaces to gain a number of desirable traits such as cloning, sorting, and enumerating.

Chapter 3 - C# Language Fundamentals

ChapterFinally,4you- Objectspent -someOrientedtimeProgramminginvestigatingwiththe C#stock collection classes defined within the

ChapSystemr 5.Collections- Exceptionamespaceand Obj ctandLifetimeexamined a number of common interfaces used by the collection-

Chapcentricer 6types- Interfaces. and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

Chapter C#7:andCallbackthe .NET Platform,Interfaces,Second Edition Delegates, and Events

by Andrew Troelsen

ISBN:1590590554

Apress © 2003 (1200 pages)

 

Overview This comprehensive text starts with a brief overview of the C# language and then quickly moves to key technical and

Up to this point inarchithe text,c uraleveryissuessamplefor .NETapplicationdevelopersyou. have developed added various bits of code to Main(), which (in some way or another) sent messages to a given object. However, you have not yet examined how an object can talk back to the entity that created it. In most programs, it is quite common for

Tableobjectsof Contentsin a system to engage in a "two-way conversation" through the use of events, callback interfaces,

C#andandotherthe .programmingNET Platform, constructsSecond Edition. To prime the pump, I begin this chapter by examining how custom

Introductioninterfaces may be used to enable callback functionality (which may ring a bell if you are a COM

Partdeveloper)One - Introducing. C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

The bulk of this chapter, however, examines various techniques provided by C# and the .NET Framework

Chapter 2 - Building C# Applications

that enable the objects in your system to engage in bidirectional communications. First, you learn about

Part Two - The C# Programming Language

the C# "delegate" keyword, which is little more than an object that "points to" other method(s) it is able to

Chapter 3 - C# Language Fundamentals make calls on when told to do so.

Chapter 4 - Object-Oriented Programming with C#

ChaptOncer 5 - Exceptions and Object Lifetime

you learn how to create and manipulate delegates (both synchronously and asynchronously), you Chapterthen investigate6 - Int rfacesthe .NETandeventCollectionsprotocol, which is based on the delegation model. Although one typically

Chapterviews events7 - Callbackwithin theInterfaccontexts, ofDelegates,GUI-basednd Eventsapplication, this chapter will illustrate how non-GUI agents

Chapterare able8 to-fireAdvancedeventsC#to theirTypeinvokersConstruction(as showTechniqulaters during our investigation of Windows Forms and

PartASPThree.NET,- theProgrammingprocess iswithidentical.NETtoAssembliesthat of firing and handling GUI-centric events).

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

UnderstandingC# andCallbackthe .NET Platform,InterfacesSe ond Edition

by Andrew Troelsen

ISBN:1590590554

As you have seen in the previous chapter, interfaces can be used to define common behaviors supported

Apress © 2003 (1200 pages)

by various types in your system. In addition to using interfaces to establish polymorphic behaviors,

This comprehensive text starts with a brief overview of the

interfaces are alsoC#commonlylanguage andusedthenas quicka callbacky movesmechanismto key technical. COM programmersand may already be familiar with the notion ofarchitecturaldefining andissuesimplementingfor .NET developerscallback interfaces. . This technique allows a COM client to receive events from a coclass using a custom COM interface, and is often used to bypass the overhead imposed by the official COM connection point architecture.

Table of Contents

C#Toandillustratethe .NETthePlatform,use of callbackSecond interfacesEdition under .NET, let's update the now familiar Car type to inform the

caller when it is about to explode (the current speed is 10 miles below the maximum speed), and has

Introduction

exploded (the current speed is at or above the maximum speed). These events will be represented by the

Part One - Introducing C# and the .NET Platform

following custom interface:

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

Part// TwoThe- ThecallbackC# ProgramminginterfaceLanguage.

Chapterpublic3 interface- C# LanguageIEngineEventsFundamentals

{

Chapter 4 - Object-Oriented Programming with C#

void AboutToBlow(string msg);

Chapter 5 - Exceptions and Object Lifetime

void Exploded(string msg);

Chapter 6 - Interfaces and Collections

}

Chapter 7 - Callback Interfaces, Delegates, and Events Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Event interfaces are not typically implemented directly by the client executable, but rather by a helper sink

Chapter 9 - Understanding .NET Assemblies

object, upon which the sender of the events (the Car type in this case) will make calls. Assume the client-

Chapter 10 - Processes, AppDomains, Contexts, and Threads

side sink class is called CarEventSink. When the Car type sends the event notification to the sink, it will

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming simply print out the incoming messages to the console:

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

// Car event sink.

Chapter 13 - Building a Better Window (Introducing Windows Forms) public class CarEventSink : IEngineEvents

Chapter 14 - A Better Painting Framework (GDI+)

{

Chapter 15 - Programming with Windows Forms Controls

private string name; // Diagnostic member to identify sink.

Chapter 16 - The System.IO Namespace

public CarEventSink(){}

Chapter 17 - Data Access with ADO.NET

public CarEventSink(string sinkName)

Part Five{ -nameWeb Applications= sinkName;and XML} Web Services

Chapterpublic18 - ASPvoid.NET WebAboutToBlow(stringPages and Web Controlsmsg)

Chapter{19Console- ASP.NET.WriteLine("{0}Web Applications reporting: {1}", name, msg); }

Chapterpublic20 - XMLvoidWeb ServicesExploded(string msg)

Index { Console.WriteLine("{0} reporting: {1}", name, msg); }

}

List of Figures

List of Tables

Now that you have a sink object that implements the event interface, your next task is to pass a reference to this sink into the Car type. The Car holds onto the reference, and makes calls back on the sink when appropriate. In order to allow the Car to obtain a reference to the sink, you can assume some method has been added to the default public interface. In keeping with the COM paradigm, let's call this method Advise(). When the object user wishes to detach from the event source, it may call another custom method on the Car type (Unadvise() in COM-speak).

Furthermore, in order to allow the call to register multiple event sinks, let's assume that the Car maintains an ArrayList to represent each outstanding connection (analogous to the array of IUnknown* types used with classic COM connection points). Here are the relevant updates:

//This Car does not make any use of the

//C# delegate or event keyword, but can

//still send out events to the caller. public class Car

if(10 == maxSpeed - currSpeed)
// Dude, you're almost dead! Proceed with caution!

{

C# and the .NET Platform, Second Edition

 

// The set of connected sinks.

ISBN:1590590554

 

by Andrew Troelsen

 

ArrayList itfConnections = new ArrayList();

 

Apress © 2003 (1200 pages)

 

 

// Attach or disconnect from the source of events.

 

Th s comprehensive text starts wi h a brief overview of the

 

public void Advise(IEngineEvents

itfClientImpl)

C# language and then quickly moves to key technical and

{ itfConnections.Add(itfClientImpl); } architectural issues for .NET developers.

public void Unadvise(IEngineEvents itfClientImpl) { itfConnections.Remove(itfClientImpl); }

...

Table of Contents

}

C# and the .NET Platform, Second Edition Introduction

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

Finally, to send the events, let's update the Car.SpeedUp() method to iterate over the list of connections

Chapter 2 - Building C# Applications

and fire the correct notification when appropriate:

Part Two - The C# Programming Language

Chapter 3 - C# Language Fundamentals

// Interface-based event protocol!

Chapter 4 - Object-Oriented Programming with C# class Car

Chapter 5 - Exceptions and Object Lifetime

{

Chapter 6 - Interfaces and Collections

...

Chapter 7 - Callback Interfaces, Delegates, and Events public void SpeedUp(int delta)

Chapter{8 - Advanced C# Type Construction Techniques

Part Three - Programming// If thewithcar.NETisAssembliesdead, send exploded event to each sink.

Chapter 9 - Understandingif(carIsDead).NET Assemblies

Chapter 10 - Processes,{ AppDomains, Contexts, and Threads

foreach(IEngineEvents e in itfConnections)

Chapter 11 - Type Re lection, Late Bind ng, and A tribute-Based Pr gramming

e.Exploded("Sorry, this car is dead...");

Part Four - Leveraging the .NET Libraries

}

Chapter 12 - Object Serialization and the .NET Remoting Layer

else

Chapter 13 - Building a Better Window (Introducing Windows Forms) Chapter 14 - A{Better Painting Framework (GDI+)

currSpeed += delta;

Chapter 15 - Programming with Windows Forms Controls Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

{

Part Five - Web Applications and XML Web Services

foreach(IEngineEvents e in itfConnections)

Chapter 18 - ASP.NET Web Pages and Web Controls

e.AboutToBlow("Careful buddy! Gonna blow!");

Chapter 19 - ASP.NET}Web Applications

Chapter 20 - XML Web Services

Index

if(currSpeed >= maxSpeed)

carIsDead = true;

List of Figures

else

 

List of Tables

Console.WriteLine("\tCurrSpeed = {0} ", currSpeed);

 

}

}

 

To wrap things up all nice and tidy, here is some client-side code, now making use of a callback interface to listen to the Car events:

// Make a car and listen to the events. public class CarApp

{

public static int Main(string[] args)

{

Car c1 = new Car("SlugBug", 100, 10);

// Make sink object.

CarEventSink sink = new CarEventSink();

// Pass the Car a reference to the sink.

C# and the .NET Platform, Second Edition c1.Advise(sink);

by Andrew Troelsen

ISBN:1590590554

// Speed up

(this will generate the events).

Apress © 2003 (1200 pages)

 

for(int i =

0; i < 6; i++)

 

This comprehensive text starts with a brief overview of the c1.SpeedUp(20);

C# language and then quickly moves to key technical and

// Detach from events.

architectural issues for .NET developers. c1.Unadvise(sink);

return 0;

}

Table of Contents

}

C# and the .NET Platform, Second Edition

Introduction

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

 

Figure 7-1 shows the end result of this interface-based event protocol.

Chapter 2 - Building C# Applications

 

Part Two - The C# Programming Language

 

Chapter

 

Chapter

C#

Chapter

 

Chapter

 

Chapter

Events

Chapter 8 - Advanced C# Type Construction Techniques

Figure 7-1: An interface-based event protocol

Part Three - Programming with .NET Assemblies

ChapterDo note9 that- Understthe Unadvise()nding .NETmethodAssembliescan be very helpful in that it allows the caller to selectively detach

Chapterfrom events10 - Processes,at will. Here,AppDomyou callins,Unadvise()Contexts, beforeand Threxitingads Main(), although this is not technically Chapternecessary11 -. However,Type R flection,assumeLatethatBinding,the applicationand Attributenow-BasedwishesProgrammingto register two sinks, dynamically remove a PartparticularFo - Leveragiduringsink the .flowNET ofLibrariesexecution, and continue processing the program at large:

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapterpublic13static- Buildinginta BetterMain(string[]Window (Introducingargs)Windows Forms)

Chapter{ 14 - A Better Painting Framework (GDI+)

Chapter //15 -MakeProgrammingcar withas Windowsusual. Forms Controls

Car c1 = new Car("SlugBug", 100, 10);

Chapter 16 - The System.IO Namespace

// Make sink objects.

Chapter 17 - Data Access with ADO.NET

Console.WriteLine("***** Creating sinks *****");

Part Five - Web Applications and XML Web Services

CarEventSink sink = new CarEventSink("First sink");

Chapter 18 - ASP.NET Web Pages and Web Controls

CarEventSink myOtherSink = new CarEventSink("Other sink");

Chapter 19 - ASP.NET Web Applications

// Hand sinks to Car.

Chapter 20 - XML Web Services

Console.WriteLine("\n***** Sending 2 sinks into Car *****");

Index

c1.Advise(sink);

List of Figures c1.Advise(myOtherSink);

List of Tables

// Speed up (this will generate the events.)

Console.WriteLine("\n***** Speeding up *****");

for(int i = 0; i < 6; i++) c1.SpeedUp(20);

// Detach first sink from events.

Console.WriteLine("\n***** Removing first sink *****");

c1.Unadvise(sink);

// Speed up again (only 'other sink' will be called.)

Console.WriteLine("\n***** Speeding up again *****");

for(int i = 0; i < 6; i++)

c1.SpeedUp(20);

// Detach other sink from events.

Console.WriteLine("\n***** Removing second sink *****");

c1.Unadvise(myOtherSink);

return 0;

}

C# and the .NET Platform, Second Edition

by Andrew Troelsen

ISBN:1590590554

Event interfaces will always have their place under any programming architecture. However, as you may

Apress © 2003 (1200 pages)

be suspecting, the .NET platform supplies native support for enabling bidirectional communications. To

This comprehensive text starts with a brief overview of the

understand this intrinsicC# languageeventandprotocol,then quicklywe beginmovesby examiningto key technicalthe roleandof the delegate type.

architectural issues for .NET developers.

SOURCE The EventInterface project is located under the Chapter 7 subdirectory.

CODE

Table of Contents

C# and the .NET Platform, Second Edition

Introduction

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

Part Two - The C# Programming Language

Chapter 3 - C# Language Fundamentals

Chapter 4 - Object-Oriented Programming with C#

Chapter 5 - Exceptions and Object Lifetime

Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

UnderstandingC# andthet ..NETNETPlatform,DelegateSecondTypeEdition

by Andrew Troelsen

ISBN:1590590554

Before formally defining .NET delegates, let's gain a bit of perspective. Historically speaking, the Windows

Apress © 2003 (1200 pages)

API makes frequent use of C-style function pointers to create entities termed callback functions or simply

This comprehensive text starts with a brief overview of the

callbacks. Using C#callbacks,languageprogrammersand then quicklyweremovesable toto configurekey technicaloneandfunction to report back to (call back) another function inarctheitecturalapplicationissues. Understandfor .NET developersthat C-style. callback functions have nothing to do with traditional COM connection points or event interfaces (however, in many ways the same end result was achieved).

Table of Contents

C#Theandproblemthe .NETwithPlatform,standardSecondC-styleEditioncallback functions is that they represent little more than a raw address

in memory. Ideally, callbacks could be configured to include additional type-safe information such as the

Introduction

number of (and types of) parameters and the return value (if any) of the method pointed to. Sadly, this is

Part One - Introducing C# and the .NET Platform

not the case in traditional callback functions, and, as you may suspect, can therefore be a frequent source

Chapter 1 - The Philosophy of .NET

of bugs, hard crashes, and other runtime disasters.

Chapter 2 - Building C# Applications

Part Two - The C# Programming Language

Nevertheless, callbacks are useful entities. In the .NET Framework, callbacks are still possible, and their

Chapter 3 - C# Language Fundamentals

functionality is accomplished in a much safer and more object-oriented manner using delegates. In

Chapter 4 - Object-Oriented Programming with C#

essence, a delegate is an object that points to another method in the application. Specifically speaking, a

Chapter 5 - Exceptions and Object Lifetime

delegate maintains three important pieces of information:

Chapter 6 - Interfaces and Collections ChapterThe7name- Callbackof theIntmethodrfaces,onDelegates,which it makesand Eventscalls

Chapter 8 - Advanced C# Type Construction Techniques

Thearguments (if any) of this method

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Thereturn value (if any) of this method

Chapter 10 - Processes, AppDomains, Contexts, and Threads

ChaptOncera11delegate- Type Reflectiohas been,createdLate Bindiandg,providedand Attributethe aforementioned-Based Programminginformation, it may dynamically PartinvokeFourthe- Leveragingmethod it representsthe .NET Librariesat runtime. As you will see, the .NET Framework automatically supports

the use of synchronous and asynchronous delegates (both of which are seen over the course of this

Chapter 12 - Object Serialization and the .NET Remoting Layer

chapter).

Chapter 13 - Building a Better Window (Introducing Windows Forms) Chapter 14 - A Better Painting Framework (GDI+)

ChapterDefining15 - Programminga Delegatewi h WiindowsC#Forms Controls

Chapter 16 - The System.IO Namespace

When you want to create a delegate in C#, you make use of (surprise, surprise) the "delegate" keyword.

Chapter 17 - Data Access with ADO.NET

Under the hood, the delegate keyword expands to a sealed class type deriving from

Part Five - Web Applications and XML Web Services

System.MulticastDelegate. For example, if you write the following C# delegate definition:

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

publicdelegate void PlayAcidHouse(Person theDJ, int volume);

Chapter 20 - XML Web Services

Index

List of Figures

the C# compiler dynamically produces a new sealed class named PlayAcidHouse deriving from

List of Tables

System.MulticastDelegate. This class is only capable of calling a method that takes two parameters (of type Person and System.Int32) and returns nothing. If you check out how this class type is represented in metadata format using ildasm.exe (Figure 7-2), you would see that the PlayAcidHouse type indeed derives from System.MulticastDelegate.

Figure 7-2: The C# "delegate" keyword represents a sealed type deriving from

Part Four - Leveraging the .NET Libraries
Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

System.MulticastDelegate.

C# and the .NET Platform, Second Edition

As you can see, theby AndrewPlayAcidHouseTroelsen class has been automaticallyISBN:1590590554endowed (thanks to the C# compiler)

with three public methodsApress © 2003. Invoke()(1200 pages)is perhaps the core method, and it may be called to inform the delegate it is timeThisto callcomprehensivethe methodtextit is currentlystarts withpointinga brief overviewto. Noticeofthatthethe parameters that are sent into

identicalC# anguage and then quickly PlayAcidHousemoves to key t chnical and

Invoke() are to the declaration of the delegate. BeginInvoke() and EndInvoke()

architectural issues for .NET developers.

provide the ability to call the current method asynchronously (Invoke(), on the other hand, makes synchronous method calls). Strangely enough, the synchronous Invoke() method is not directly callable

from C#. As you will see in just a bit, Invoke() is called behind the scenes when you make use of the

Table of Contents appropriate C# syntax.

C# and the .NET Platform, Second Edition

IntroductionNow, how exactly does the compiler know how to prototype the Invoke(), BeginInvoke(), and EndInvoke()

Partmethods?One - IntroducingTo understandC# andthetheprocess,.NET Platformhere is the crux of the generated PlayAcidHouse class type (the

Chapteritems in1bold- TherepresentPhilosophytheofauto.NET-generated items):

Chapter 2 - Building C# Applications

Part Two - The C# Programming Language

sealed class PlayAcidHouse : System.MulticastDelegate

Chapter 3 - C# Language Fundamentals

{

Chapter 4 - ObjectPlayAcidHouse(object-Oriented Programming wi h C#

public target, uint functionAddress);

Chapter public5 - Ex eptionsvoid andInvoke(Obj ctPersonLifetime theDJ, int volume);

Chapter public6 - InterfacesIAsyncResultand Collec ionsBeginInvoke(Person theDJ, int volume,

Chapter 7 - AsyncCallbackInterfaces, Delegates,cb, objectand Eventsstate);

public void EndInvoke(IAsyncResult result);

Chapter 8 - Advanced C# Type Construction Techniques

}

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

First, notice that the parameters that are defined for the Invoke() and BeginInvoke() members (in addition to the mandatory AsyncCallback and System.Object parameters of the BeginInvoke() method) are the

same number of, and type of, the original C# delegate declaration. Likewise, the return value of Invoke()

Chapter 12 - Object Serialization and the .NET Remoting Layer

and EndInvoke() is identical to the original C# delegate declaration. And obviously, the name of the

Chapter 13 - Building a Better Window (Introducing Windows Forms) constructor is based on the name of the original C# delegate declaration.

Chapter 14 - A Better Painting Framework (GDI+)

ChapterNow assume15 - Programmingyou have definedwith WindowsanotherFormsC# delegateControlstype that represents a method returning a string and

Chaptertaking three16 - TheBooleans:System.IO Namespace

Chapter 17 - Data Access with ADO.NET

PartpublicFive - Wdelegateb Applicationsstringand XMLTakeSomeBools(boolWeb Services a, bool b, bool c);

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

This time, the auto-generated class breaks down as follows:

Chapter 20 - XML Web Services

Index

sealed class TakeSomeBools : System.MulticastDelegate

Li t of Figures

{

List of Tables

public TakeSomeBools(object target, uint functionAddress);

public string Invoke(bool a, bool b, bool c);

public IAsyncResult BeginInvoke(bool a, bool b, bool c,

AsyncCallback cb, object state);

public string EndInvoke(IAsyncResult result);

}

Finally, understand that delegates can also "point to" methods that contain out and ref parameters:

public delegate string TakeSomeBoolsByRefAndAsOut

(out bool a, out bool b, ref bool c);

In this case, the signatures of the Invoke() and BeginInvoke() methods look as you would expect; however, check out the EndInvoke() method, which now pads the first set of parameters with the set of out/ref

arguments from the delegate:

 

C# and the .NET Platform, Second Edition

 

 

by Andrew Troelsen

ISBN:1590590554

sealed class TakeSomeBoolsByRefAndAsOut : System.MulticastDelegate

{

Apress © 2003 (1200 pages)

 

This comprehensive text starts with a brief overview of the

public TakeSomeBoolsByRefAndAsOut (object target, uint functionAddress);

C# language and then quickly moves to key technical and

public string Invoke(out bool a, out bool b, ref bool c); architectural issues for .NET developers.

public IAsyncResult BeginInvoke(out bool a, out bool b, ref bool c, AsyncCallback cb, object state);

Table of Contentspublic string EndInvoke(out bool a, out bool b,

ref bool c, IAsyncResult result);

C# and the .NET Platform, Second Edition

}

Introduction

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

I think you can see the general pattern: A C# delegate definition results in a sealed class with three auto-

Part Two - The C# Programming Language

generated methods whose parameter and return types are based on the delegate's declaration. We will

Chapter 3 - C# Language Fundamentals

see exactly how we interact with Invoke(), BeginInvoke(), and EndInvoke() in just a bit, but first let's check

Chapter 4 - Object-Oriented Programming with C# out the System.MulticastDelegate base class.

Chapter 5 - Exceptions and Object Lifetime Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

Members ofC#Systemand he .NET.MulticastDelegateP atform, Second Edi ion

by Andrew Troelsen

ISBN:1590590554

So then, when you build a type using the C# "delegate" keyword, you indirectly declare a type that derives

Apress © 2003 (1200 pages)

from System.MulticastDelegate. The MulticastDelegate type in turn derives from System.Delegate (as well as

This comprehensive text starts with a brief overview of the implements two standardC# languageinterfaces)and then. Herequicklyis themovesformalto keydefinitiontechnicalof MulticastDelegate:and

architectural issues for .NET developers.

public abstract class MulticastDelegate :

Delegate, ICloneable, ISerializable

Table of Contents

{

C# and the .NET Platform, Second Edition

public MethodInfo Method { get; }

Introduction

public object Target { get; }

Part One - Introducing C# and the .NET Platform

public virtual object Clone();

Chapter 1 - The Philosophy of .NET

public object DynamicInvoke(object[] args);

Chapter 2 - Building C# Applications

public virtual bool Equals(object obj);

Part Two - The C# Programming Language

public virtual int GetHashCode();

Chapter 3 - C# Language Fundamentals

public virtual Delegate[] GetInvocationList();

Chapter 4 - Object-Oriented Programming with C# public virtual void

Chapter 5 GetObjectData(SerializationInfoExceptions and ct Lifet me info, StreamingContext context);

Chapterpublic6 - InterfacesType GetType();and Collections

Chapterpublic7 - CallbackvirtualInterfaces,stringDelegates,ToString();a d Events

}

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

And here is the definition of System.Delegate:

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

public abstract class Delegate : object,

Part Four - Leveraging the .NET Libraries

ICloneable, ISerializable

Chapter 12 - Object Serialization and the .NET Remoting Layer

{

Chapter 13 - Building a Better Window (Introducing Windows Forms)

public MethodInfo Method { get; }

Chapter 14 - A Better Painting Framework (GDI+) public object Target { get; }

Chapter 15 - Programming with Windows Forms Controls public virtual object Clone();

Chapter 16 - The System.IO Namespace

public static Delegate Combine(Delegate a, Delegate b);

Chapter 17 - Data Access with ADO.NET

public static Delegate Combine(Delegate[] delegates);

Part Five - Web Applications and XML Web Services

public static Delegate

Chapter 18 - ASP.NET Web Pages and Web Controls

CreateDelegate(Type type, System.Reflection.MethodInfo method);

Chapter 19 - ASP.NET Web Applications

public static Delegate

Chapter 20 - XML Web Services

CreateDelegate(Type type, object target, string method);

Indexpublic static Delegate CreateDelegate(Type type, Type target, string method);

List ofpublicFigures static Delegate CreateDelegate(Type type,

List of Tablesobject target, string method, bool ignoreCase); public object DynamicInvoke(object[] args);

public virtual bool Equals(object obj); public virtual int GetHashCode();

public virtual Delegate[] GetInvocationList();

public virtual void GetObjectData(SerializationInfo info, StreamingContext context);

public Type GetType();

public static Delegate Remove(Delegate source, Delegate value); public virtual string ToString();

}

Together, these two base classes provide the necessary infrastructure for the derived type to wrap and invoke a method on the fly. Table 7-1 documents the key members to be aware of.

Chapter 10 - Processes, AppDomains, Contexts, and Threads
Chapter 9 - Understanding .NET Assemblies
Part Three - Programming with .NET Assemblies

Table 7-1: Select Members of System.MultcastDelegate/System.Delegate

C# and the .NET Platform, Second Edition

 

Inherited

by AndrewMeaningTroelsenin Life

ISBN:1590590554

 

Member

Apress © 2003 (1200 pages)

 

 

 

 

 

 

 

Method

This

 

comprehensive text starts with a brief overview of the

 

 

 

This property returns the name of a static method that is maintained by the

 

 

C# language and then quickly moves to key technical and

 

 

architecturaldelegate.issues for .NET developers.

 

 

 

 

 

 

 

Target

 

 

If the method to be called is defined at the object level (rather than a static

Table of Contents

 

 

method), Target returns the name of the method maintained by the delegate.

 

 

If the value returned from Target equals null, the method to be called is a

C# and the .NET Platform,

 

 

Second Edition

 

 

Introduction

 

 

static member.

 

 

 

 

 

 

 

 

 

 

 

PartCombine()One - Introducing C# andThisthestatic.NETmethodPlatformadds a method to the list maintained by the delegate. In

C#, you trigger this method using the overloaded += operator as a shorthand

Chapter 1 - The Philosophy of .NET

notation.

Chapter 2 - Building C# Applications

 

 

 

 

 

 

 

 

Part Two - The C# Programming Language

 

 

 

 

GetInvocationList()

 

This method returns an array of System.Delegate types, each representing a

 

 

Chapter 3 - C# Language Fundamentals

 

 

 

 

 

 

 

particular method that may be invoked.

 

 

 

Chapter 4 - Object-Oriented Programming with C#

 

 

 

 

 

 

 

Remove()

 

This static method removes a delegate from the list methods to call. In C#,

 

 

 

Chapter 5

- Exceptions and Object Lifetime

 

 

 

 

Chapter 6

 

 

you trigger this method using the overloaded -= operator as a shorthand

 

 

 

- Interfaces and Collections

 

 

 

 

 

 

 

notation.

 

 

 

 

Chapter 7

- Callback Interfaces, Delegates, and Events

 

 

Chapter 8

- Advanced C# Type Construction Techniques

As you may be able to infer from Table 7-1, delegates are capable of pointing to multiple methods. Under the hood, the System.Delegate type defines a linked list that is used to hold onto each method maintained by a given delegate. Additional methods can be added to this internal list using the static Combine() method (or

using the C# overloaded += operator). To remove a method from the internal list, call the static Remove()

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

method (or the C# overloaded -= operator). As you may know, the ability for a delegate to call multiple

Part Four - Leveraging the .NET Libraries

functions is termed multicasting . You see this technique action a bit later in this chapter.

Chapter 12 - Object Serialization and the .NET Remoting Layer Chapter 13 - Building a Better Window (Introducing Windows Forms) Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

The SimplestC# andPossiblethe .NET Platform,DelegateSecondExampleEdition

by Andrew Troelsen

ISBN:1590590554

Delegates can tend to cause a great deal of confusion when encountered for the first time. Thus, to get

Apress © 2003 (1200 pages)

the ball rolling, let's take a look at a very simple example. Here is the complete code, with analysis to

This comprehensive text starts with a brief overview of the follow: C# language and then quickly moves to key technical and

architectural issues for .NET developers.

namespace SimpleDelegate

{

Table of Contents

class DelegateApp

C# and the .NET Platform, Second Edition

{

Introduction

// This is the method that will be called

Part One - Introducing C# and the .NET Platform

// by the delegate.

Chapter 1 - The Philosophy of .NET

public static void PlainPrint(string msg)

Chapter 2 - Building C# Applications

{ Console.WriteLine("Msg is: {0}", msg); }

Part Two - The C# Programming Language

// Define a delegate type.

Chapter 3 - C# Language Fundamentals

public delegate void AnyMethodTakingAString(string s);

Chapter 4 - Object-Oriented Programming with C# public static void Main()

Chapter 5 - Exceptions{ and Object Lifetime

Chapter 6 - Interfaces//andMakeCollectionsthe delegate.

Chapter 7 - CallbackAnyMethodTakingAStringInterfaces, Delegates, and Eventsdel;

del = new AnyMethodTakingAString(PlainPrint);

Chapter 8 - Advanced C# Type Construction Techniques

// AnyMethodTakingAString.Invoke() called here!

Part Three - Programming with .NET Assemblies

del("Hello there...");

Chapter 9 - Understanding .NET Assemblies

// Dump info about the delegate.

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Console.WriteLine("I just called: {0}", del.Method);

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

}

Part Four - Leveraging the .NET Libraries

Chapter }12

- Object Serialization and the .NET Remoting Layer

Chapter}

13

- Building a Better Window (Introducing Windows Forms)

Chapter 14

- A Better Painting Framework (GDI+)

Chapter 15

- Programming with Windows Forms Controls

Here, you begin by declaring a .NET delegate type using the C# "delegate" keyword. The

Chapter 16

- The System.IO Namespace

AnyMethodTakingAString delegate represents an object that maintains a reference to some method that

Chapter 17

- Data Access with ADO.NET

takes a single string parameter and returns nothing. When you want to assign the target (i.e., the method

Partto call)Fiveof- Weba givenApplicationsdelegate,andsimplyXMLpassWebinServicesthe name of the method to the delegate's constructor. At this

Chapterpoint, you18 -areASPable.NETtoWebindirectlyPagesinvokeand WebtheControlsmember using a syntax that looks like a direct function

Chapterinvocation:19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

// Make the delegate.

ListAnyMethodTakingAStringof Figures del;

Listdelof Tables= new AnyMethodTakingAString(PlainPrint);

del("Hello there...");

// Dump info about the delegate.

Console.WriteLine("I just called: {0}", del.Method);

Notice that when you print out the method maintained by the delegate (using the Method property), you see that each parameter is automatically mapped to the corresponding .NET system type (when you run this example, notice the presence of the System.Void type, which is a language-neutral way to denote a method with no return value).

Now recall that a delegate object could care less about the actual name of the method it is responsible for invoking. If you want, you could dynamically change the target method as follows:

class DelegateApp

{

public static void PlainPrint(string msg)

C# and the .NET Platform, Second Edition

 

{ Console.WriteLine("Msg is: {0}", msg); }

by Andrew Troelsen

ISBN:1590590554

public static void UpperCasePrint(string msg)

Apress © 2003 (1200 pages)

{ Console.WriteLine("Msg is: {0}", msg.ToUpper()); }

This comprehensive text starts with a brief overview of the public static void XXXXYYYYZZZZ888777aaa(string msg)

C# language and then quickly moves to key technical and

{ Console.WriteLine("Msg is: {0}", msg); } architectural issues for .NET developers.

public delegate void AnyMethodTakingAString(string s); public static void Main()

{

Table of Contents

AnyMethodTakingAString del;

C# and the .NET Platform, Second Edition

del = new AnyMethodTakingAString(PlainPrint);

Introduction

del("Hello there...");

Part One - Introducing C# and the .NET Platform

Console.WriteLine("->I just called: {0}\n", del.Method);

Chapter 1 - The Philosophy of .NET

// Reassign and invoke delegate.

Chapter 2 - Building C# Applications

del= new AnyMethodTakingAString(UpperCasePrint);

Part Two - The C# Programming Language

del("Hello there...");

Chapter 3 - C# Language Fundamentals

Console.WriteLine("->I just called: {0}\n", del.Method);

Chapter 4 - Object-Oriented Programming with C#

// Reassign and invoke delegate.

Chapter 5 - Exceptions and Object Lifetime

del= new AnyMethodTakingAString(XXXXYYYYZZZZ888777aaa);

Chapter 6 - Interfaces and Collections

del("Hello there...");

Chapter 7 - CallbackConsoleInterfaces,.WriteLine("Del gates,->IandjustEventscalled: {0}\n", del.Method);

Chapter}8 - Advanced C# Type Construction Techniques

Part} Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

The final output can be seen in Figure 7-3.

 

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

 

Chapter

Layer

Chapter

Forms)

Chapter

 

Chapter

 

Chapter

 

Chapter

 

Part

 

Chapter 18 - ASP.NET Web Pages and Web Controls

Figure 7-3: Dynamically "pointing to" various methods

Chapter 19 - ASP.NET Web Applications

ChapterIf you attempt20 - XMLto WebassignServicesthe address of a method that did not match the delegate's declaration:

Index

List of Figures

// Bad target!

List of Tables int x, System.AppDomain y public void BadTargetForDelegate( )

{

// Stuff...

}

...

// This is not a valid target! Error!

del = new AnyMethodTakingAString(BadTargetForDelegate);

del("Huh?!?");

you are (thankfully) issued the following compile time error (note the bold text that highlights the crux of

the error):

C:\Books\C# Book Second Edition\Code\Chapter

7\SimpleDelegate\SimpleDel.cs(53): Method

'SimpleDelegate.DelegateApp.BadTargetForDelegate(int, System.AppDomain)'

does not match delegate 'void

C# and the .NET Platform, Second Edition

 

SimpleDelegate.DelegateApp.AnyMethodTakingAString(string)'

by Andrew Troelsen

ISBN:1590590554

Apress © 2003 (1200 pages)

This comprehensive text starts with a brief overview of the

Multicasting with .NET Delegates

C# language and then quickly moves to key technical and architectural issues for .NET developers.

The final point to be made with this simple delegate example is the fact that a single delegate object may be configured to point to numerous methods. When you wish to insert multiple methods into the invocation

Tablelist maintainedof Cont ntsby the System.Delegate base class, you are able to make use of the overloaded +=

operator. The topic of operator overloading will be examined in detail in the next chapter, but for the time

C# and the .NET Platform, Second Editi n

being simply understand that when you apply the += operator to a type derived from

Introduction

System.MulticastDelegate, the hidden Combine() method is triggered automatically (so be sure to check

Part One - Introducing C# and the .NET Platform

out the CIL via ildasm.exe).

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

Part// TwoNow- ThesomeC#multicastingProgramming Language.

AnyMethodTakingAString myMultiCaster;

Chapter 3 - C# Language Fundamentals

myMultiCaster = new AnyMethodTakingAString(PlainPrint);

Chapter 4 - Object-Oriented Programming with C#

myMultiCaster += new AnyMethodTakingAString(UpperCasePrint);

Chapter 5 - Exceptions and Object Lifetime

myMultiCaster += new AnyMethodTakingAString(XXXXYYYYZZZZ888777aaa);

Chapter 6 - Interfaces and Collections

myMultiCaster("Here is a string");

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

SOURCE The SimpleDelegate project is located under the Chapter 7 subdirectory.

Chapter 10 - Processes, AppDomains, Contexts, and Threads

CODE

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

Building a MoreC# and Elaboratethe .NET Platform,DelegateS cond EditionExample

by Andrew Troelsen

ISBN:1590590554

To illustrate a more advanced use of delegates, let's begin by updating the Car class to include two new Boole

Apress © 2003 (1200 pages)

member variables. The first is used to determine if your automobile is due for a wash (isDirty); the other

This comprehensive text starts with a brief overview of the

represents if the carC# languagein questionandisthenin needquicklyof amovestire rotationto key(shouldRotate)technical and . To enable the object user to interact with this new statearchitecturaldata, Car alsois uesdefinesfor .NETsomedevelopersadditional. properties and an updated constructor. Here is the story so far:

Table of Contents

// Another updated Car class.

C# and the .NET Platform, Second Edition

public class Car

Introduction

{

Part One - Introducing C# and the .NET Platform

...

Chapter 1 - The Philosophy of .NET

// NEW! Are we in need of a wash? Need to rotate tires?

Chapter 2 - Building C# Applications private bool isDirty;

Part Two - The C# Programming Language

private bool shouldRotate;

Chapter 3 - C# Language Fundamentals

Chapter 4 - Object-Oriented Programming with C#

// Extra params to set bools.

Chapter public5 - Ex eptionsCar(stringand Objectname,Lif timeint max, int curr, bool dirty, bool rotate)

Chapter {6 - Interfaces and Collections

Chapter 7 - Callback... Interfaces, Delegates, and Events

isDirty = dirty;

Chapter 8 - Advanced C# Type Construction Techniques

shouldRotate = rotate;

Part Three - Programming with .NET Assemblies

}

Chapter 9 - Understanding .NET Assemblies

public bool Dirty // Get and set isDirty.

Chapter 10 - Processes, AppDomains, Contexts, and Threads

{

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

get{ return isDirty; }

Part Four - Leveraging the .NET Libraries

set{ isDirty = value; }

Chapter 12 - Object Serialization and the .NET Remoting Layer

}

Chapter 13 - Building a Better Window (Introducing Windows Forms)

public bool Rotate // Get and set shouldRotate.

Chapter 14 - A Better Painting Framework (GDI+)

{

Chapter 15 - Programming with Windows Forms Controls get{ return shouldRotate; }

Chapter 16 - The System.IO Namespace

set{ shouldRotate = value; }

Chapter 17 - Data Access with ADO.NET

}

Part Five - Web Applications and XML Web Services

}

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

ChapterNow, assume20 - XMLyouWebhaveServicesdeclared the following delegate (which, again, is nothing more than an object-oriented

wrapper around a function pointer) within your current namespace:

Index

List of Figures

List//ofThisTablesdelegate is actually a class encapsulating a function pointer

// to 'some method', taking a Car as a parameter, and returning void.

public delegate void CarDelegate(Car c);

Here, you have created a delegate named CarDelegate. The CarDelegate type represents "some function" taking a Car as a parameter and returning void.

Delegates As Nested Types

Currently, your delegate is decoupled from its logically related Car type (given that you have simply declared th CarDelegate type within the defining namespace). While there is nothing horribly wrong with this approach, a more enlightened alternative would be to define the CarDelegate directly within the Car class:

// This time, define the delegate as part of the class definition.

public class Car

{

...

}

C# and the .NET Platform, Second Edition

// This is represented in CIL as

by Andrew Troelsen ISBN:1590590554

// Car$CarDelegate (i.e., a nested type).

Apress © 2003 (1200 pages)

public delegate void CarDelegate(Car c);

This comprehensive text starts with a brief overview of the C# language and then quickly moves to key technical and architectural issues for .NET developers.

Given that the "delegate" keyword produces a new class deriving from System.MulticastDelegate, the

Table of Contents

CarDelegate is in fact a nested type definition! If you check ildasm.exe (see Figure 7-4), you will see the truth o

C# and the .NET Platform, Second Edition the matter.

Introduction

Part One - Introducing C# and the .NET Platform

Chapter

Chapter

Part

Chapter

 

Chapter

C#

Chapter

 

Chapter

 

Chapter

Events

Chapter

Techniques

Part

 

Chapter

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Figure 7-4: Remember! C# delegate types alias System.MulticastDelegate

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Using the CarDelegate

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Now that you have a type that points to "some function" taking a Car parameter and returning nothing, you can

Chapter 15 - Programming with Windows Forms Controls

create other functions that take this delegate as a parameter. To illustrate, assume you have a new class name

Chapter 16 - The System.IO Namespacollection

Garage. This type maintains a of Car types contained in an ArrayList. Upon creation, the ArrayList is

Chapterfilled with17 some- DatainitialAccessCarwitypesh ADO. .NET

Part Five - Web Applications and XML Web Services

More importantly, the Garage class defines a public ProcessCars() method, which takes a single argument of

Chapter 18 - ASP.NET Web Pages and Web Controls

type Car.CarDelegate. In the implementation of ProcessCars(), you pass each Car in your collection as a

Chapter 19 - ASP.NET Web Applications

parameter to the "function pointed to" by the delegate.

Chapter 20 - XML Web Services

Index

To help keep your wits about you, ProcessCars() also makes use of two members defined by the

List of Figures

System.MulticastDelegate class (Target and Method) to determine exactly which function the delegate is

List of Tables

currently pointing to. Here, then, is the complete definition of the Garage class:

// The Garage class has a method that makes use of the CarDelegate.

Using System.Collections;

...

public class Garage

{

// A list of all cars in the garage.

ArrayList theCars = new ArrayList();

// Create the cars in the garage.

public Garage()

{

// Recall, we updated the ctor to set isDirty and shouldRotate.

theCars.Add(new Car("Viper", 100, 0, true, false)); theCars.Add(new Car("Fred", 100, 0, false, false)); theCars.Add(new Car("BillyBob", 100, 0, false, true));

theCars.Add(new Car("Bart", 100, 0, true, true));

C# and the .NET Platform, Second Edition theCars.Add(new Car("Stan", 100, 0, false, true));

}

by Andrew Troelsen

ISBN:1590590554

 

 

Apress © 2003 (1200 pages)

// This method takes a Car.CarDelegate as a parameter.

This comprehensive textnothings arts with a brief overview of the

// Therefore 'proc' is more than a function pointer!

C# language and then quickly moves to key technical and public void ProcessCars(Car.CarDelegate proc)

architectural issues for .NET developers.

{

// Diagnostics: Where are we forwarding the call?

Console.WriteLine("***** Calling: {0} *****",

Table of Contents

d.Method.ToString());

C# and the .NET Platform, Second Edition

// Diagnostics: Are we calling an instance method or a static method?

Introduction

if(proc.Target != null)

Part One - Introducing C# and the .NET Platform

Console.WriteLine("->Target: {0} ", proc.Target.ToString());

Chapter 1 - The Philosophy of .NET else

Chapter 2 - Building C# Applications

Console.WriteLine("->Target is a static method");

Part Two - The C# Programming Language

// Real Work: Now call the method, passing in each car.

Chapter 3 - C# Language Fundamentals foreach(Car c in theCars)

Chapter 4 - Object-Oriented Programming with C# proc(c);

Chapter 5 - Exceptions and Object Lifetime

}

Chapter 6 - Interfaces and Collections

}

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

When the object user calls ProcessCars(), it will send in the name of the method that should handle this reque

Part Three - Programming with .NET Assemblies

For the sake of argument, assume these are static members named WashCar() and RotateTires(). Consider th

Chapter 9 - Understanding .NET Assemblies

following usage:

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

// The garage delegates all work orders to these static functions

Part Four - Leveraging the .NET Libraries

// (finding a good mechanic is always a problem...)

Chapter 12 - Object Serialization and the .NET Remoting Layer

public class CarApp

Chapter 13 - Building a Better Window (Introducing Windows Forms)

{

Chapter 14 - A Better Painting Framework (GDI+)

// A target for the delegate.

Chapter 15 - Programming with Windows Forms Controls

public static void WashCar(Car c)

Chapter 16 - The System.IO Namespace

{

Chapter 17 - Data Access with ADO.NET if(c.Dirty)

Part Five - Web Applications and XML Web Services

Console.WriteLine("Cleaning a car");

Chapter 18 - ASP.NET Web Pages and Web Controls else

Chapter 19 - ASP.NET Web Applications

Console.WriteLine("This car is already clean...");

Chapter 20 - XML Web Services

}

Index // Another target for the delegate.

List of Figures

public static void RotateTires(Car c)

List of Tables

{

if(c.Rotate)

Console.WriteLine("Tires have been rotated");

else

Console.WriteLine("Don't need to be rotated...");

}

public static int Main(string[] args)

{

// Make the garage.

Garage g = new Garage();

// Wash all dirty cars.

g.ProcessCars(new Car.CarDelegate(WashCar));

// Rotate the tires.

g.ProcessCars(new Car.CarDelegate(RotateTires));

return 0;

}

Part Five - Web Applications and XML Web Services

}

C# and the .NET Platform, Second Edition

 

by Andrew Troelsen

ISBN:1590590554

Notice (of course)Apressthat the© 2003two(1200staticpages)methods are an exact match to the delegate type (void return value and a single Car argument)This .comprehensiveAlso, recall thattextwhenstartsyouwithpassa briefin theoverviewname ofofyourthe function as a constructor parameter, you are adding thisC#itemlanguageto theainternald then quicklylinked listmovesmaintainedto key technicalby Systemand.MulticastDelegate. Figure 7-5 shows th

architectural issues for .NET developers.

output of this test run. (Notice the output messages supplied by the Target and Method properties.)

Table

C# and

Part

Chapter

Chapter

Part

Chapter

Chapter

Chapter

Chapter 6 - Interfaces and Collections

Figure 7-5: Passing the buck

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

PartAnalyzingThree - Pro rammingthe Delegationwith .NET AssembliesCode

Chapter 9 - Understanding .NET Assemblies

ChapterAs you10can- see,Processes,the Main()AppDomains,method beginsContexts,byandcreatingThreadsan instance of the Garage type. This class has been Chapterconfigured11 -toTypedelegateReflection,all workLatetoBinding,other namedand Attributestatic-functionsBased Programming. Now, when you write the following:

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

// Wash all dirty cars.

Chapterg.ProcessCars(new13 - Building BetterCarWindow.CarDelegate((IntroducingWashCarWindows));Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

what you are effectively saying is "Add a pointer to the WashCar() function to the CarDelegate type, and pass t

Chapter 16 - The System.IO Namespace

delegate to Garage.ProcessCars()." Like most real-world garages, the real work is delegated to another part of

Chapter 17 - Data Access with ADO.NET

the system (which explains why a 30-minute oil change takes 2 hours). Given this, you can assume that

ProcessCars()actually looks like the following under the hood:

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

// CarDelegate points to the WashCar function:

Chapter 20 - XML Web Services

public void ProcessCars(Car.CarDelegate proc)

Index

{

List of Figures

...

List of Tables

foreach(Car c in theCars)

proc(c); // proc(c) => CarApp.WashCar(c)

}

Likewise, if you say:

// Rotate the tires.

g.ProcessCars(new Car.CarDelegate(RotateTires));

ProcessCars() can be understood as:

// CarDelegate points to the RotateTires function:

public void ProcessCars(Car.CarDelegate proc)

{

...

}

C# and the .NET Platform, Second Edition

foreach(Car c in theCars)

by Andrew Troelsen

ISBN:1590590554

proc(c);

// proc(c) => CarApp.RotateTires(c)

Apress © 2003 (1200 pages)

This comprehensive text starts with a brief overview of the C# language and then quickly moves to key technical and architectural issues for .NET developers.

Also notice that when you are calling ProcessCars(), you must create a new instance of the custom delegate:

Table of Contents

// Wash all dirty cars.

C# and the .NET Platform, Second Edition

g.ProcessCars(newCar.CarDelegate(WashCar));

Introduction

// Rotate the tires.

Part One - Introducing C# and the .NET Platform

g.ProcessCars(newCar.CarDelegate(RotateTires));

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

Part Two - The C# Programming Language

This might seem odd at first, given that a delegate represents a function pointer. However, remember that this

Chapter 3 - C# Language Fundamentals

function pointer is represented by an instance of type System.MulticastDelegate, and therefore must be "new-

Chaptered." 4 - Object-Oriented Programming with C#

Chapter 5 - Exceptions and Object Lifetime

Chapter 6 - Interfaces and Collections

Multicasting with the Car.CarDelegate

Chapter 7 - Callback Interfaces, Delegates, and Events

ChapterRecall 8that-aAdvancedmulticastC#delegateType Constructionis an objectTechniquesthat is capable of calling any number of functions. In the current

Partexample,Three -youProgrammingdo not makewithuse.NETof thisAssembliesfeature. Rather, you make two calls to Garage.ProcessCars(), sending in

Chapternew instance9 - Understandingof the CarDelegate.NET Assemblieseach time. However, assume you have updated Main() to look like the

Chapterfollowing:10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

// Add two function pointers to the internal linked list.

Chapter 12 - Object SerializationMain(string[]and the .NET Remoting Layer

public static int args)

Chapter{ 13 - Building a Better Window (Introducing Windows Forms)

Chapter //14 -MakA BetterthePaintinggarageFramework. (GDI+)

Chapter Garage15 - Programmi= newg withGarage();Windows Forms Controls

// Create two new delegates.

Chapter 16 - The System.IO Namespace

Car.CarDelegate wash = new Car.CarDelegate(WashCar);

Chapter 17 - Data Access with ADO.NET

Car.CarDelegate rotate = new Car.CarDelegate(RotateTires);

Part Five - Web Applications and XML Web Services

// The overloaded + operator can be applied to multicast delegates.

Chapter 18 - ASP.NET Web Pages and Web Controls

// The result is a new delegate that maintains pointers to

Chapter 19 - ASP.NET Web Applications

// both functions.

Chapter 20 - XML Web Services

g.ProcessCars(wash + rotate);

Index

return 0;

List of Figures

}

List of Tables

Here, you begin by creating two new CarDelegate objects, each of which points to a given function. When you call ProcessCars(), you are actually passing in a new delegate that holds each function pointer within the intern linked list (crazy huh?). Do note that the + operator is simply a shorthand for calling the static Delegate.Combine() method. Thus, you could write the following equivalent (but uglier) code:

// The + operator has the same effect as calling the Combine() method.

g.ProcessCars((Car.CarDelegate)Delegate.Combine(wash, rotate));

Furthermore, if you wish to hang onto the new delegate for later use, you could write the following instead:

// Create two new delegates.

Car.CarDelegate wash = new Car.CarDelegate(WashCar);

Car.CarDelegate rotate = new Car.CarDelegate(RotateTires);

// Store the new delegate for later use.

C# and the .NET Platform, Second Edition

MulticastDelegate d = wash + rotate;

by Andrew Troelsen ISBN:1590590554

// Send the new delegate into the ProcessCars() method.

Apress © 2003 (1200 pages)

g.ProcessCars((Car.CarDelegate)d);

This comprehensive text starts with a brief overview of the

C# language and then quickly moves to key technical and

architectural issues for .NET developers.

Regardless of how you configure a multicast delegate, understand that when you call Combine() (or use the overloaded + operator), you are adding a new function pointer to the internal list. If you wish to remove an item

from this internal linked list, you can call the static Remove() method. The first parameter marks the delegate y

Table of Contents

wish to manipulate, while the second parameter marks the item to remove:

C# and the .NET Platform, Second Edition

Introduction

// The static Remove() method returns a Delegate type.

Part One - Introducing C# and the .NET Platform

Delegate washOnly = MulticastDelegate.Remove(d, rotate);

Chapter 1 - The Philosophy of .NET

g.ProcessCars((Car.CarDelegate)washOnly);

Chapter 2 - Building C# Applications

Part Two - The C# Programming Language

Chapter 3 - C# Language Fundamentals

Before you view the output of this program, let's also update ProcessCars() to print out each function pointer

Chapterstored in4 the- Objectlinked-Orientedlist usingProgrammingDelegate.GetInvocationList()with C# . This method returns an array of Delegate objects,

Chapterwhich you5 -iterateExc ptionsover usingand Objectforeach:Lifetime

Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

// Now print out each member in the linked list.

Chapter 8 - AdvancedProcessCars(CarC# Type Const uctionCarDelegateT chniques public void . proc)

Part{ Three - Programming with .NET Assemblies

Chapter //9 -WhereUnderstarendingwe.NETpassingAs embliesthe call?

Chapter 10foreach(Delegate- Pro esses, AppDomains,d inContexts,proc.andGetInvocationListThreads ())

Chapter {11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - LeveragingConsolethe.WriteLine("*****.NET Libraries Calling: {0} *****",

d.Method.ToString());

Chapter 12 - Object Serialization and the .NET Remoting Layer

}

Chapter 13 - Building a Better Window (Introducing Windows Forms)

...

Chapter 14 - A Better Painting Framework (GDI+)

}

Chapter 15 - Programming with Windows Forms Controls Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

PartInstanceFive - W b MethodsApplicati ns andAsXMLCallbacksWeb Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Currently, the CarDelegate type is storing pointers to static functions. This is not a requirement of the delegate

Chapter 19 - ASP.NET Web Applications

protocol (unlike C-based callbacks, which require static members). It is also possible to delegate a call to a

Chapter 20 - XML Web Services

method defined on any object instance. To illustrate, assume that the WashCar() and RotateTires() methods

Index

have now been moved into a new class named ServiceDept:

List of Figures

List of Tables

// We have now moved the static functions into a helper class.

public class ServiceDept

{

// Not static!

public void WashCar(Car c)

{

if(c.Dirty)

Console.WriteLine("Cleaning a car");

else

Console.WriteLine("This car is already clean...");

}

// Still not static!

public void RotateTires(Car c)

{

if(c.Rotate)

Console.WriteLine("Tires have been rotated");

C# and the .NET Platform, Second Edition else

by Andrew Troelsen ISBN:1590590554

Console.WriteLine("Don't need to be rotated...");

}Apress © 2003 (1200 pages)

}This comprehensive text starts with a brief overview of the C# language and then quickly moves to key technical and architectural issues for .NET developers.

You could now update Main() as follows:

Table of Contents

// Delegate to instance methods of the ServiceDept type.

C# and the .NET Platform, Second Edition

public static int Main(string[] args)

Introduction

{

Part One - Introducing C# and the .NET Platform

// Make the garage.

Chapter 1 - The Philosophy of .NET

Garage g = new Garage();

Chapter 2 - Building C# Applications

// Make the service department.

Part Two - The C# Programming Language

ServiceDept sd = new ServiceDept();

Chapter 3 - C# Language Fundamentals

// The garage delegates the work to the service department.

Chapter 4

- Object-Oriented Programming with C#

Car.CarDelegate wash = new Car.CarDelegate(sd.WashCar);

Chapter 5

- Exceptions and Object Lifetime

Car.CarDelegate rotate = new Car.CarDelegate(sd.RotateTires);

Chapter 6

- Interfaces and Collections

MulticastDelegate d = wash + rotate;

Chapter 7

- Ca lback Interfaces, Delegates, and Events

// Tell the garage to do some work.

Chapter g8.ProcessCars((Car- Advanced C# Type Const.CarDelegate)d);uction Techniques

Part Threereturn- P ogramming0; with .NET Assemblies

Chapter} 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Figure 7-6 shows the final fruits of our labor.

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter Forms)

Chapter

Chapter

Chapter

Chapter

Part

Chapter

Chapter

Chapter

Index

List of

List of

Figure 7-6: Passing the buck yet again

SOURCE The CarDelegate project is located under the Chapter 7 subdirectory.

CODE

Understanding Asynchronous Delegates

Now that you have some experience with the synchronous behavior of .NET delegate types, let's examine how invoke methods asynchronously. First off, what exactly warrants an asynchronous method invocation? As you a fully aware, some programming operations take time. For example, if you build a word processing application that has the ability to print the current document, and that document happens to be 1000 pages in length, the computer's CPU has the potential to spin away for quite some time.

Now assume that this application has all of its programming logic taking place within the Main() method using a

singlethread. Simply put, a thread is a path of execution within a .NET application. Single-threaded applications

C# and the .NET Platform, Second Edition

 

are quite simple to program; however, in the case of the word processor application, the end user is far less tha

by Andrew Troelsen

ISBN:1590590554

pleased. The reason has to do with the fact that while the application's single thread of execution is crunching o

Apress © 2003 (1200 pages)

the 1000-page document, all other aspects of this program (such as menu activation, toolbar clicking, and

This comprehensive text starts with a brief overview of the keyboard input) are unresponsive.

C# language and then quickly moves to key technical and

architectural issues for .NET developers.

When programmers wish to build applications that are able to simulate numerous tasks performing "at the sam time," they will typically spawn additional threads to perform background tasks (e.g., printing documents) while

the main thread is still able to respond to basic user-input needs.

Table of Contents

C#So,andwhatthedoes.NETthreadingPlatform, Secondhave toEditiondo with .NET delegates? Well, to illustrate the potential problem with

Introductionsynchronous delegate invocations, ponder the following simple application:

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

using System;

Chapter 2 - Building C# Applications

using System.Threading;

Part Two - The C# Programming Language

Chnamespacept r 3 - C# Language Fundamentals

AsyncDelegate

Chapter{ 4 - Object-Oriented Programming with C#

Chapter //5 -AExcnewptionsdelegateand ObjecttypeLif time.

Chapter public6 - Interfacesdelegateand Collectionsstring NewCarDelegate(Car carToDetail);

public class Car{...}

Chapter 7 - Callback Interfaces, Delegates, and Events

class App

Chapter 8 - Advanced C# Type Construction Techniques

{

Part Three - Programming with .NET Assemblies

Chapter 9

- Understandingpublic static.NET Assembliesstring DetailCar(Car c)

Chapter 10

- Processes,{

AppDomains, Contexts, and Threads

Chapter 11

- Type Reflection,// DetailingLate Binding,a andcarAttributetakes-Based10 seconds.Programming

Console.WriteLine("Detailing car on thread {0}",

Part Four - Leveraging the .NET Libraries

Thread.CurrentThread.GetHashCode());

Chapter 12 - Object Serialization and the .NET Remoting Layer

Thread.Sleep(10000);

Chapter 13 - Building a Better Window (Introducing Windows Forms) return "Your car is ready!";

Chapter 14 - A Better Painting Framework (GDI+)

}

Chapter 15 - Programming with Windows Forms Controls

 

static void Main(string[] args)

Chapter 16 - The System.IO Namespace

 

{

Chapter 17 - Data Access with ADO.NET

 

Console.WriteLine("Main() is on thread {0}",

Part Five - Web Applications and XML Web Services

 

Thread.CurrentThread.GetHashCode());

Chapter 18 - ASP.NET Web Pages and Web Controls

 

NewCarDelegate d = new NewCarDelegate(DetailCar);

Chapter 19 - ASP.NET Web Applications

 

Car myCar = new Car();

Chapter 20 - XML Web Services

 

Console.WriteLine(d(myCar));

Index

Console.WriteLine("Done invoking delegate");

List of Figures

}

List of Tables}

 

}

 

First, notice that this example makes use of a new namespace named System.Threading. Chapter 10 will fully examine the details of multithreading within the .NET platform; however, to frame the use of asynchronous delegates, simply understand this namespace defines a type named Thread, which provides a static method named CurrentThread(). If you obtain the hash code for the current thread, you (in effect) obtain a unique identifier for the currently executing thread.

Here, you print out the hash code of the current thread within Main(), and then synchronously invoke the NewCarDelegate type. Once the flow of execution passes into the DetailCar() helper function, you print out the hash code of the active thread once again and put it to sleep (which is to say, stop all activity on said thread) for 10 seconds. Given this, you will not see the final message of Main() print to the console until approximately 10 seconds after the delegate's invocation.

When you run this example, note that the same hash code has been printed twice, signifying the fact that your

application is performing all work on a single thread of execution. Now, in many cases, this behavior may be

C# and the .NET Platform, Second Edition

perfectly acceptable. However, given that the DetailCar() method takes 10 seconds to complete, your applicatio

by Andrew Troelsen ISBN:1590590554

appears to be hanging until the call has completed (just like the printing of the 1000-page document).

Apress © 2003 (1200 pages)

The question thereforeThis comprehensiveis: How can youtexttellstartsa delegatewith a briefto invokeoverviewa methodof the on a separate thread of execution an "report back" to theC#mainlanguagethreadndoncethenthequicklymethodmoveshastocompleted?key technicalTheandgood news is that every .NET delegate

architectural issues for .NET developers.

type is automatically equipped with this ability. The even better news is that you are not required to directly dive into the details of the System.Threading namespace to do so (although these entities can quite naturally work

hand in hand).

Table of Contents

C#Again,and thefull.detailsNET Platoform,multithreadedSecond Editionprogramming will be examined later in this text, but for the time being, let's

Introductioncheck out how System.MulticastDelegate provides automatic support for asynchronous method invocations.

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

Invoking Methods Asynchronously

Chapter 2 - Building C# Applications

PartAs youTworecall,- The C#whenProgrammingthe C# compilerLanguageprocesses the "delegate" keyword, you dynamically receive two methods Chnamedpt r 3BeginInvoke()- C# LanguageandFundamentalsEndInvoke(). Thus, for the NewCarDelegate type, you are provided with the following

Chaptermembers:4 - Object-Oriented Programming with C#

Chapter 5 - Exceptions and Object Lifetime

Chapter 6 - Interfaces and Collections

public IAsyncResult BeginInvoke(Car carToDetail,

Chapter 7 - Callback Interfaces, Delegates, and Events

System.AsyncCallback callback, object state);

Chapterpublic8 string- AdvancedEndInvoke(IAsyncResultC# Type Construction Techniquesresult);

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Note that BeginInvoke() returns an IAsyncResult interface, while EndInvoke() requires an IAsyncInvoke type as

Chapter 10 - Processes, AppDomains, Contexts, and Threads

parameter. This interface (defined in the System namespace) breaks down as follows:

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

public interface IAsyncResult

Chapter 12 - Object Serialization and the .NET Remoting Layer

{

Chapter 13 - Building a Better Window (Introducing Windows Forms)

object AsyncState { get; }

Chapter 14 - A Better Painting Framework (GDI+)

WaitHandle AsyncWaitHandle { get; }

Chapter 15 - Programming with Windows Forms Controls

bool CompletedSynchronously { get; }

Chapter 16 - The System.IO Namespace

bool IsCompleted { get; }

Chapter 17 - Data Access with ADO.NET

}

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

In the simplest case, one is able to effectively ignore directly interacting with these members. All you have to do

Chcachepter 20 - XML Web Services

the returned IAsyncResult type in a local variable in order to pass it to EndInvoke() when you are ready t

Indexobtain the result of the method invocation. Thus, to invoke DetailCar() asynchronously, you simply need to mak

ListtheoffollowingFigures updates:

List of Tables

static void Main(string[] args)

{

Console.WriteLine("Main() is on thread {0}",

Thread.CurrentThread.GetHashCode());

NewCarDelegate d = new NewCarDelegate(DetailCar);

Car myCar = new Car();

IAsyncResult itfAR = d.BeginInvoke(myCar, null, null);

Console.WriteLine("Done invoking delegate");

// Do other work...

string msg = d.EndInvoke(itfAR); // Get the result. Console.WriteLine(msg);

}

Before viewing the output, a point must be made regarding Visual Studio .NET. As you were typing in the

C# and the .NET Platform, Second Edition

 

previous code updates, you may have noticed that IntelliSense failed to show you the BeginInvoke() and

by Andrew Troelsen

ISBN:1590590554

EndInvoke() members. The reason is due to the fact that these methods don't exist until the current assembly

Apress © 2003 (1200 pages)

has been compiled! Recall that the C# compiler will autogenerate a type derived from System.MulticastDelega

Thus,This comprehensive text starts with a brief overview of the

atcompile time. when you are invoking members asynchronously, always remember that you are smarter

C# language and then quickly moves to key technical and

than any IDE. As long as you are mindful of the parameters and return value of the member you are invoking, architectural issues for .NET developers.

you will be able to type in the code for BeginInvoke()/EndInvoke() accordingly. Now, check out Figure 7-7.

Table

C# and

Part

Platform

Chapter

ChapterFigure2 - 7Building-7: AsynchronousC# Applicatinvocations increase program responsiveness.

Part Two - The C# Programming Language

Here, you can see that two threads of execution are working to perform the work of the program (automatically

Chapter 3 - C# Language Fundamentals

In addition to the unique hash codes, you will also be able to see upon running the application that the "Done

Chapter 4 - Object-Oriented Programming with C#

invoking delegate" message displays immediately, while the secondary thread is busy attending to its business

Chapter 5 - Exceptions and Object Lifetime

this case, sleeping on the job for 10 seconds).

Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

SOURCE The AsyncDelegate project is located under the Chapter 7 subdirectory.

Chapter 8 - Advanced C# Type Construction Techniques

CODE

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Callbacks for Asynchronous Delegates

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

So far, so good. At this point, you are able to trigger a method via a custom delegate and obtain the result at

Part Four - Leveraging the .NET Libraries

some time in the future (e.g., when you call the EndInvoke() method). While this is all well and good, there may

Chapter 12 - Object Serialization and the .NET Remoting Layer

be times when you would rather not manually call EndInvoke() to obtain the results of your invocation, but woul

Chapter 13

- Building Better Window (Introducing Windows Forms)

rather that the delegate call you when the method has been completed. In many ways, this functionality is quite

Chapter 14

- A Better Pa ing Framework (GDI+)

similar to the callback interface pattern examined at the opening of this chapter. To understand the connection,

let's break down the parameters to the BeginInvoke() method generated for the NewCarDelegate type:

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

 

Chapter 17 - Data Access with ADO.NET

 

public IAsyncResult BeginInvoke(

// All delegate parameters are listed firs

Part Five - Web Applications and XML Web Services

Car carToDetail,

 

Chapter 18 - ASP.NET Web Pages and Web Controls

// A standard delegate for the callback.

System.AsyncCallback

callback,

Chapter 19 - ASP.NET Web Applcations

 

// Allows the calling

thread to pass information to the callback.

Chapterobject20 - XMLstateWeb Services

Index);

List of Figures

List of Tables

Note that the second parameter to BeginInvoke() is (get this) another delegate. In this case, System.AsyncCallback is a system-defined delegate that knows how to call methods that match the following prototype:

void SomeCallBackFunction(IAsyncResult itfAR)

When you wish to inform the delegate to call you back when the asynchronous invocation is complete, pass in instance of the AsyncCallback type as the second parameter to BeginInvoke() and build a static (or instancelevel) method to receive the call. Here is the complete code update, with analysis to follow (note the extra and required namespace reference):

using System;

using System.Threading;

using System.Runtime.Remoting.Messaging;

namespace AsyncCallbackDelegate

C# and the .NET Platform, Second Edition

{

by Andrew Troelsen

ISBN:1590590554

// The

delegate.

 

public

Apress © 2003 (1200 pages)

delegate string NewCarDelegate(Car carToDetail);

public

This comprehensive text starts with a brief overview of the

classC# languageCar{and...then}

quickly moves to key technical and

class App

architectural issues for .NET developers.

{

public static void DetailCarCallBack(IAsyncResult itfAR)

Table of Contents{

Console.WriteLine("DetailCarCallBack on thread {0}",

C# and the .NET Platform, Second Ed tion

Introduction

Thread.CurrentThread.GetHashCode());

// Get message from DetailCar().

Part One - Introducing C# and the .NET Platform

AsyncResult res = (AsyncResult)itfAR;

Chapter 1 - The Philosophy of .NET

NewCarDelegate d = (NewCarDelegate)res.AsyncDelegate;

Chapter 2 - Building C# Applications

Console.WriteLine(d.EndInvoke(itfAR));

Part Two - The C# Programming Language

}

Chapter 3 - C# Language Fundamentals

public static string DetailCar(Car c)

Chapter 4 - Object-Oriented Programming with C#

{

Chapter 5 - Exceptions and Object Lifetime

// Detail car for 10 seconds.

Chapter 6 - Interfaces and Collections

Console.WriteLine("Detailing car on thread {0}",

Chapter 7 - Callback Interfaces, Delegates, and Events

Thread.CurrentThread.GetHashCode());

Chapter 8 - Advanced C# Type Construction Techniques

Thread.Sleep(10000);

Part Three - Programming with .NET Assemblies

return "Your car is ready!";

Chapter 9 - Understanding .NET Assemblies

}

Chapter 10 - Processes, AppDomains, Contexts, and Threads

static void Main(string[] args)

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

{

Part Four - LeveragingConsolethe .NET Libraries.WriteLine("Main() is on thread {0}",

Chapter 12 - Object SerializationThreadand.theCurrentThread.NET Remoting Lay.GetHashCode());r Chapter 13 - Building aNewCarDelegateBetter Window (Introducing= newWindoNewsCarDelegate(DetailCar);Forms) Chapter 14 - A Better PaintingCar myCarFr mework= new(GDI+)Car();

// Call asynchronously via callback.

Chapter 15 - Programming with Windows Forms Controls

d.BeginInvoke(myCar, new AsyncCallback(DetailCarCallBack), null);

Chapter 16 - The System.IO Namespace

Console.WriteLine("Done invoking delegate");

Chapter 17 - Data Access with ADO.NET

// Keep console alive until call completes.

Part Five - Web Applications and XML Web Services

Console.ReadLine();

Chapter 18 - ASP.NET Web Pages and Web Controls

}

Chapter 19 - ASP.NET Web Applications

}

Chapter 20 - XML Web Services

}

Index

List of Figures

List of Tables

First of all, notice that you now have a new helper function named DetailCarCallBack that will be invoked by the delegate when the DetailCar() method has completed. As well, notice that this time you are not caching the IAsyncResult type returned from BeginInvoke(), given that Main() is no longer required to call EndInvoke()!

Now, let's look at the implementation of DetailCarCallBack(). After printing out the hash code of the current thread (which logically should be the same number as the thread that is calling DetailCar()), you find the following lines of (technically optional) code:

public static void DetailCarCallBack(IAsyncResult itfAR)

{

...

// Get message from DetailCar().

AsyncResult res = (AsyncResult)itfAR;

NewCarDelegate d = (NewCarDelegate)res.AsyncDelegate;

Console.WriteLine(d.EndInvoke(itfAR));

}

C# and the .NET Platform, Second Edition

Recall that the DetailCar() method returns a string message that informs the user that the operation has

by Andrew Troelsen

ISBN:1590590554

completed. In the previous interaction of this example, Main() directly called EndInvoke() to obtain the return

Apress © 2003 (1200 pages)

value of the "method pointed to" by the NewCarDelegate. However, now that the delegate will call

This comprehensive text starts with a brief overview of the

DetailCarCallBack() at some time in the future, this method needs to be the entity in charge of this task.

C# language and then quickly moves to key technical and

architectural issues for .NET developers.

Here, you cast the incoming parameter into a System.Runtime.Remoting.Messaging.AsyncResult type and obtain the underlying delegate type (NewCarDelegate) via the AsyncDelegate property (this new namespace

defines numerous types used when leveraging the .NET Remoting layer, as you will see later in this text). Once

Table of Contents

you have a handle to the delegate that is calling your callback method, you are able to indeed call EndInvoke()

C# and the .NET Platform, Second Edition

obtain the textual message from DetailCar().

Introduction

Part One - Introducing C# and the .NET Platform

Cool! At this point you have dug into the details of synchronous and asynchronous delegate invocations. To be

Chapter 1 - The Philosophy of .NET

sure, there are additional techniques that may be used when asynchronously invoking a member, and you will

Chapter 2 - Building C# Applications

see further examples where necessary. As you will see over the remainder of this text, this same asynchronous

Part Two - The C# Programming Language

pattern is used when invoking file access methods, remote types, XML Web services, and whatnot.

Chapter 3 - C# Language Fundamentals

SOURCE The AsyncCallbackDelegate project is located under the Chapter 7 subdirectory.

Chapter 4 - Object-Oriented Programming with C#

CODE

Chapter 5 - Exceptions and Object Lifetime

Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

Part Two - The C# Programming Language
Chapter 2 - Building C# Applications
Chapter 1 - The Philosophy of .NET

UnderstandingC# and(andthe .NETUsing)Platform,EventsS cond Edition

by Andrew Troelsen

ISBN:1590590554

Delegates are fairly interesting constructs because you can resolve the name of a function to call at runtime,

Apress © 2003 (1200 pages)

rather than at compile time. Admittedly, this syntactic orchestration can take a bit of getting used to. However,

This comprehensive text starts with a brief overview of the

because the abilityC#forlanguageone objectand tothencallquicklyback tomovesanotherto keyobjectte hnicalis suchanda helpful construct, C# provides the "event" keyword toarchitecturallessen theissuesburdenforof.NETusingdevdelegateslopers. in the raw.

The most prevalent use of the "event" keyword would be found in GUI-based applications, in which Button,

TableTextBox,of Contentsand Calendar widgets all report back to the containing Form when a given action (such as clicking a C#Button)and thehas.NEToccurredPlatform,. However,Second Editionevents are not limited to GUI-based applications. Indeed, they can be quite

helpful when creating non-GUI-based projects (as you will now see).

Introduction

Part One - Introducing C# and the .NET Platform

Recall that the current implementation of Car.SpeedUp() (as of Chapter 4) throws an exception if the user attempts to increase the speed of an automobile that has already been destroyed. This is a rather brute force way to deal with the problem, given that the exception has the potential to halt the program's execution if the

error is not handled in an elegant manner. A better design would be to simply inform the object user when the

Chapter 3 - C# Language Fundamentals

car has died using a custom event, and allow the caller to act accordingly.

Chapter 4 - Object-Oriented Programming with C#

ChapterLet's reconfigure5 - Exc ptionsthe CarndtoObjectsend twoLifetimeevents to those who happen to be listening. The first event

Chapter(AboutToBlow)6 - Interfaceswill beandsentCollectionswhen the current speed is 10 miles below the maximum speed. The second event Chapter(Exploded)7 - willCallbeacksentInterfaces,when theDelegates,user attemptsand Eventsto speed up a car that is already dead. Establishing an event is

a two-step process. First, you need to define a delegate, which will be used to hold onto the set of methods

Chapter 8 - Advanced C# Type Construction Techniques

that will be called when the event occurs. Next, you define the events themselves using the C# "event"

Part Three - Programming with .NET Assemblies

keyword, which as you can see is defined in terms of the related delegate. Here are the initial updates:

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter// This11 -carTypecanReflection,'talkLateback'Binding,toandtheAttributeuser-.Based Programming

PartpublicFour - classLeveragingCarthe .NET Libraries

{

Chapter 12 - Object Serialization and the .NET Remoting Layer

...

Chapter 13 - Building a Better Window (Introducing Windows Forms)

// Is the car alive or dead?

Chapter 14 - A Better Painting Framework (GDI+)

private bool carIsDead;

Chapter 15 - Programming with Windows Forms Controls

// Holds the function(s) to call when the event occurs.

Chapter 16 - The System.IO Namespace

public delegate void EngineHandler(string msg);

Chapter 17 - Data Access with ADO.NET

// This car can send these events.

Part Five - Web Applications and XML Web Services

public static event EngineHandler Exploded;

Chapter 18 - ASP.NET Web Pages and Web Controls

public static event EngineHandler AboutToBlow;

Chapter 19 - ASP.NET Web Applications

...

Chapter 20 - XML Web Services

}

Index

List of Figures

List of Tables

Firing an event is as simple as specifying the event by name and sending out any specified parameters as defined by the related delegate. To illustrate, update the previous implementation of SpeedUp() to send each event accordingly (and remove the previous exception logic):

// Fire the correct event based on our current state of affairs.

public void SpeedUp(int delta)

{

// If the car is dead, send exploded event.

if(carIsDead)

{

if(Exploded != null)

Exploded("Sorry, this car is dead...");

}

else

{

currSpeed += delta;

C# and the .NET Platform, Second Edition

// Almost dead? Send about to blow event.

by Andrew Troelsen

currSpeed)

ISBN:1590590554

if(10 == maxSpeed -

 

Apress © 2003 (1200 pages)

!= null)

 

if(AboutToBlow

 

This comprehensive text starts with a brief overview of the

AboutToBlow("Careful, approaching terminal speed!");

C# language and then quickly moves to key technical and

// Still OK! Proceed as usual. architectural issues for .NET developers.

if(currSpeed >= maxSpeed) carIsDead = true;

else

Table of Contents

Console.WriteLine("\tCurrSpeed = {0} ", currSpeed);

C# and the .NET Platform, Second Edition

}

Introduction

}

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

Chapter 2 - Building C# Applications

With this, you have configured the car to send two custom events (under the correct conditions). You will see ParttheTwousage- Theof thisC# Programmingnew automobileLanguagein just a moment, but first, let's check the event architecture in a bit more

Chapterdetail. 3 - C# Language Fundamentals

Chapter 4 - Object-Oriented Programming with C#

Note Notice how you are checking the event against a null object reference before firing. This is to ensure

Chapter 5 - Exceptions and Object Lifetime

that if the caller did not register to listen to a given event, it is not sent into sweet oblivion.

Chapter 6 - Interfaces and Collections

Chapter 7 - Callback Interfaces, Delegates, and Events

ChaptEventsr 8 - UnderAdvanced theC# TypeHoodC nstruction Techniques

Part Three - Programming with .NET Assemblies

A given event actually expands into two hidden public functions, one having an "add_" prefix, the other having

Chapter 9 - Understanding .NET Assemblies

a "remove_" prefix. For example, the Exploded event expands to the following methods:

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

// The following event expands in CIL code to:

Part Four - Leveraging the .NET Libraries

// add_Exploded()

Chapter 12 - Object Serialization and the .NET Remoting Layer

// remove_Exploded()

Chapter 13 - Building a Better Window (Introducing Windows Forms)

public static event EngineHandler Exploded;

Chapter 14 - A Better Painting Framework (GDI+) Chapter 15 - Programming with Windows Forms Controls Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

In addition to defining hidden add_XXX() and remove_XXX() methods, each event also actually maps to a

Part Five - Web Applications and XML Web Services

private class, which associates the corresponding delegate to a given event. In this way, when an event is

Chapter 18 - ASP.NET Web Pages and Web Controls

raised, each method maintained by the delegate will be called. This is a convenient way to allow an object to

Chapter 19 - ASP.NET WebmultipleAp lications

broadcast the event to event sinks. To illustrate, check out Figure 7-8, which shows the Car type as

Chapterseen through20 - XMLtheWebeyesServof ildasmces .exe.

Index

List of Figures

List of Tables

Second Edition

ISBN:1590590554

with a brief overview of the moves to key technical and

developers.

Table

C# and

Part

Chapter

Chapter

Part

Chapter

Chapter

C#

Chapter

ChapterFigure6 - 7Interfaces-8: Asynchronousand Collectionsinvocations via callbacks

Chapter 7 - Callback Interfaces, Delegates, and Events

As you can see, each event (Exploded and AboutToBlow) is internally represented as the following members:

Chapter 8 - Advanced C# Type Construction Techniques

Part Three - Programming with .NET Assemblies

A private class

Chapter 9 - Understanding .NET Assemblies

ChapterAn10add- _Processes,XXX() methodAppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

A remove_XXX() method

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

If you were to check out the CIL instructions behind add_AboutToBlow(), you would find the following (note the

Chapter 13 - Building a Better Window (Introducing Windows Forms) call to Delegate.Combine() is handled on your behalf):

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

.method public hidebysig specialname static

Chapter 16 - The System.IO Namespace

void add_AboutToBlow(class CarEvents.Car/EngineHandler 'value')

Chapter 17 - Data Access with ADO.NET

cil

managed synchronized

Part Five - Web Applications and XML Web Services

{

 

 

Chapter 18 - ASP.NET Web Pages and Web Controls

// Code size

22 (0x16)

Chapter 19 - ASP.NET Web Applications

.maxstack

2

 

Chapter 20 - XML Web Services

 

IL_0000:

ldsfld class CarEvents.Car/EngineHandler CarEvents.Car::AboutToBlow

IndexIL_0005:

ldarg.0

 

List of Figures

call class [mscorlib]System.Delegate

IL 0006:

List of Tables[mscorlib]System.Delegate::Combine

(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)

IL_000b:

castclass

CarEvents.Car/EngineHandler

IL_0010:

stsfld

 

class CarEvents.Car/EngineHandler CarEvents.Car::AboutToBlow

IL_0015:

ret

 

} // end of

method Car::add_AboutToBlow

As you would expect, remove_AboutToBlow() will make the call to Delegate.Remove() automatically:

.method public hidebysig specialname static

void

remove_AboutToBlow(class CarEvents.Car/EngineHandler 'value')

cil managed synchronized

{

22 (0x16)

// Code size

Part Five - Web Applications and XML Web Services
Chapter 17 - Data Access with ADO.NET

.maxstack 2

C# and the .NET Platform, Second Edition

IL_0000: ldsfld class CarEvents.Car/EngineHandler CarEvents.Car::AboutToBlow

by Andrew Troelsen

ISBN:1590590554

IL_0005: ldarg.0

 

Apress © 2003 (1200 pages)

IL_0006: call class [mscorlib]System.Delegate

This comprehensive text starts with a brief overview of the

[mscorlib]System.Delegate::Remove

 

C# language and then quickly moves to key technical and

(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate)

IL_000b:

architectural issues for .NET developers.

castclass

CarEvents.Car/EngineHandler

IL_0010:

stsfld

class CarEvents.Car/EngineHandler

CarEvents.Car::AboutToBlow

Table of Contents

IL_0015: ret

C# and the .NET Platform, Second Edition

} // end of method Car::remove_AboutToBlow

Introduction

Part One - Introducing C# and the .NET Platform

Chapter 1 - The Philosophy of .NET

The CIL instructions for the event itself make use of the [.addon] and [.removeon] directives to establish the

Chapter 2 - Building C# Applications

correct add_XXX and remove_XXX methods (also note the private class is mentioned by name):

Part Two - The C# Programming Language

Chapter 3 - C# Language Fundamentals

.event CarEvents.Car/EngineHandler AboutToBlow

Chapter 4 - Object-Oriented Programming with C#

{

Chapter 5 - Exceptions and Object Lifetime

.addon void CarEvents.Car::add_AboutToBlow(class CarEvents.Car/EngineHandler)

Chapter 6 - Interfaces and Collections

.removeon void CarEvents.Car::remove_AboutToBlow

Chapter 7 - Callback Interfaces,Car/EngineHandler)Delegates, Events

(class CarEvents.

Chapter} // end8 - Advancedof eventC#Car::AboutToBlowType Constructi n Techniques

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

So, now that you understand how to build a class that can send events, the next big question is how you can

Chapter 10 - Processes, AppDomains, Contexts, and Threads

configure an object to receive these events.

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

ChapterListening12 - ObjecttoSerializationIncomingand Eventsthe .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Assume you have now created an instance of the Car class and wish to listen to the events it is capable of

Chapter 14 - A Better Painting Framework (GDI+)

sending. The goal is to create a method that represents the event sink that will be called by the related

Chapter 15 - Programming with Windows Forms Controls

delegate. To bind this method to the event, you need to call the correct add_XXX() method to ensure that your

Chapter 16 - The System.IO Namespace

method is added to the list of function pointers maintained by the EngineHandler delegate. However, you cannot call the CIL add_XXX() and remove_XXX() directly, but rather use the overloaded += and -= operators.

Thus, when you wish to listen to an event, follow the pattern shown here:

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

// I'm listening...

Chapter 20 - XML Web Services

// ObjectVariable.EventName += new ObjectVariable.DelegateName(functionToCall);

Index

Car.Exploded += new Car.EngineHandler(OnBlowUp);

List of Figures

List of Tables

When you wish to detach from a source of events, use the -= operator:

//Shut up already!

//ObjectVariable.EventName -= new ObjectVariable.DelegateName(functionToCall);

Car.Exploded -= new Car.EngineHandler(OnBlowUp);

Here is the complete code:

// Make a car and listen to the events. public class CarApp

{

public static int Main(string[] args)

{

Car c1 = new Car("SlugBug", 100, 10);

// Hook into events.

C# and the .NET Platform, Second Edition

Car.Exploded += new Car.EngineHandler(OnBlowUp);

by Andrew Troelsen ISBN:1590590554

Car.AboutToBlow += new Car.EngineHandler(OnAboutToBlow);

Apress © 2003 (1200 pages)

// Speed up (this will generate the events.)

for(intTh s comprehensive text starts with a brief overview of the i = 0; i < 10; i++)

C# language and then quickly moves to key technical and c1.SpeedUp(20);

architectural issues for .NET developers.

// Detach from events.

Car.Exploded -= new Car.EngineHandler(OnBlowUp);

Car.Exploded -= new Car.EngineHandler(OnAboutToBlow);

Table of Contents

// No response!

C# and the .NET Platform, Second Edition

for(int i = 0; i < 10; i++)

Introduction

c1.SpeedUp(20);

Part One - Introducing C# and the .NET Platform

return 0;

Chapter 1 - The Philosophy of .NET

}

Chapter 2 - Building C# Applications

// OnBlowUp event sink.

Part Two - The C# Programming Language

public static void OnBlowUp(string s)

Chapter 3 - C# Language Fundamentals

{

Chapter 4 - Object-Oriented Programming with C#

Console.WriteLine("Message from car: {0} ", s);

Chapter 5 - Exceptions and Object Lifetime

}

Chapter 6 - Interfaces and Collections

// OnAboutToBlow event sink.

Chapter public7 - CallbackstaticInterfaces,voidDelegates,OnAboutToBlow(stringand Events s)

Chapter {8 - Advanced C# Type Construction Techniques

Part Three - ProgrammingConsole.withWriteLine("Message.NET Assemblies from car: {0} ", s);

Chapter }9 - Understanding .NET Assemblies

}

Chapter 10 - Processes, AppDomains, Contexts, and Threads

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

If you wish to have multiple event sinks called by a given event, simply repeat the process:

Chapter

12

- Object Serialization and the .NET Remoting Layer

Chapter

13

- Building a Better Window (Introducing Windows Forms)

Chapter// Multiple14 - A BettereventPaintingsinks.Framework (GDI+)

Chapterpublic15class- ProgrammingCarAppwith Windows Forms Controls

Chapter{

16

- The System.IO Namespace

public static int Main(string[] args)

Chapter

17

- Data Access with ADO.NET

Part Five{ - Web Applications and XML Web Services

Chapter

18

// Make a car as usual.

- ASP.NET Web Pages and Web Controls

Chapter

19

Car c1 = new Car("SlugBug", 100, 10);

- ASP.NET Web Applications

Chapter

20

- XML Web Services

Index

 

// Hook into events.

 

Car.Exploded += new Car.EngineHandler(OnBlowUp);

 

 

List of Figures Car.Exploded += new Car.EngineHandler(OnBlowUp2);

List of Tables Car.AboutToBlow += new Car.EngineHandler(OnAboutToBlow);

//Speed up (this will generate the events.) for(int i = 0; i < 10; i++)

c1.SpeedUp(20);

...

//Detach from events when desired.

Car.Exploded -= new Car.EngineHandler(OnBlowUp);

Car.Exploded -= new Car.EngineHandler(OnBlowUp2);

Car.Exploded -= new Car.EngineHandler(OnAboutToBlow);

...

}

// OnBlowUp event sink A.

public static void OnBlowUp(string s)

{Console.WriteLine("Message from car: {0} ", s); }

//OnBlowUp event sink B.

public static void OnBlowUp2(string s)

C# and the .NET Platform, Second Edition

{ Console.WriteLine("AGAIN I say: {0} ", s); }

by Andrew Troelsen

ISBN:1590590554

// OnAboutToBlow event sink.

 

Apress © 2003 (1200 pages)

public static void OnAboutToBlow(string s)

This comprehensive text starts with a brief overview of the

{ Console.WriteLine("Message from car: {0} ", s); }

C# language and then quickly moves to key technical and

}

architectural issues for .NET developers.

Now, when the Exploded event is sent, the associated delegate calls OnBlowUp() as well as OnBlowUp2(), as

Table of Contents

 

shown in Figure 7-9.

 

C# and the .NET Platform, Second Edition

 

Introduction

 

Part

 

Chapter

 

Chapter

 

Part

 

Chapter

 

Chapter

C#

Chapter

 

Chapter

 

Chapter

Events

Chapter

Techniques

Part Three - Programming with .NET Assemblies

Figure 7-9: Hooking into the engine events

Chapter 9 - Understanding .NET Assemblies

Chapter 10 - Processes, AppDomains, Contexts, and Threads

ChapterNote11 VS- Type.NETReflection,2003 furtherLate simplifiesBinding, andeventAt ributehandling-Based. WhenProgrammingyou apply the + syntax to an object's event, Part Four - Leveragingyou may usethethe.NETTabLibrarieskey to automatically generate the delegate target.

Chapter 12 - Object Serialization and the .NET Remoting Layer

ChapterObjects13 - BuildingAs Eventa BetterSinksW dow (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

ChapterAt this point,15 - Pryougramminghave thewithbackgroundWindows toFormsbuildCobjectsntrols that can participate in a two-way conversation.

However, understand that you are free to build a helper object to respond to an object's event set, much in the

Chapter 16 - The System.IO Namespace

same way that you created a helper class to be called by all delegates. For example, let's move your event

Chapter 17 - Data Access with ADO.NET

sink methods out of the CarApp class and into a new class named CarEventSink:

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter// Car19event- ASP.NETsinkWeb Applications

public class CarEventSink

Chapter 20 - XML Web Services

{

Index

// OnBlowUp event handler.

List of Figures

public void OnBlowUp(string s)

List of Tables

{Console.WriteLine("Message from car: {0} ", s); } // OnBlowUp event handler version 2.

public void OnBlowUp2(string s)

{Console.WriteLine("AGAIN I say: {0} ", s); }

// OnAboutToBlow handler.

public void OnAboutToBlow(string s)

{ Console.WriteLine("Message from car: {0} ", s); }

}

The CarApp class is then a bit more self-contained, as the event sink methods have been pulled out of the CarApp definition and into their own custom type. Here is the update:

// Note the creation and use of the CarEventSink.

public class CarApp

{

C# and the .NET Platform, Second Edition public static int Main(string[] args)

{ by Andrew Troelsen ISBN:1590590554

Apress © 2003 (1200 pages)

This comprehensive text starts with a brief overview of the

Car c1 = new Car("SlugBug", 100, 10);

C# language and then quickly moves to key technical and

// Make the sink object. architectural issues for .NET developers.

CarEventSink sink = new CarEventSink();

// Hook into events using sink object.

Car.Exploded += new Car.EngineHandler(sink.OnBlowUp);

Table of Contents

Car.Exploded += new Car.EngineHandler(sink.OnBlowUp2);

C# and the .NET Platform, Second Edition

Car.AboutToBlow += new Car.EngineHandler(sink.OnAboutToBlow);

Introduction

for(int i = 0; i < 10; i++)

Part One - Introducing C# and the .NET Platform

c1.SpeedUp(20);

Chapter 1 - The Philosophy of .NET

// Detach from events using sink object.

Chapter 2 - Building C# Applications

Car.Exploded -= new Car.EngineHandler(sink.OnBlowUp);

Part Two - The C# Programming Language

Car.Exploded -= new Car.EngineHandler(sink.OnBlowUp2);

Chapter 3 - C# Language Fundamentals

Car.Exploded -= new Car.EngineHandler(sink.OnAboutToBlow);

Chapter 4 - Object-Oriented Programming with C# return 0;

Chapter 5 - Exceptions and Object Lifetime

}

Chapter 6 - Interfaces and Collections

}

Chapter 7 - Callback Interfaces, Delegates, and Events

Chapter 8 - Advanced C# Type Construction Techniques

The output is (of course) identical.

Part Three - Programming with .NET Assemblies

Chapter 9 - Understanding .NET Assemblies

SOURCE The CarEvents project is located under the Chapter 7 subdirectory.

Chapter 10 - Processes, AppDomains, Contexts, and Threads

CODE

Chapter 11 - Type Reflection, Late Binding, and Attribute-Based Programming

Part Four - Leveraging the .NET Libraries

Chapter 12 - Object Serialization and the .NET Remoting Layer

Chapter 13 - Building a Better Window (Introducing Windows Forms)

Chapter 14 - A Better Painting Framework (GDI+)

Chapter 15 - Programming with Windows Forms Controls

Chapter 16 - The System.IO Namespace

Chapter 17 - Data Access with ADO.NET

Part Five - Web Applications and XML Web Services

Chapter 18 - ASP.NET Web Pages and Web Controls

Chapter 19 - ASP.NET Web Applications

Chapter 20 - XML Web Services

Index

List of Figures

List of Tables

Соседние файлы в предмете Программирование