<< Show C # >> Chapter 8 with C # write components (revised)

zhaozj2021-02-08  311

Chapter 8 uses C # write components

This chapter is about writing components with C #. How do you learn how to write a component, how to compile it, and how to use it in a client program. A more deep step is to organize your app with your name space.

This chapter consists of two major sizes:

. Your first component

. Working with namespace

8.1 Your first component

So far, the examples mentioned in this book are directly used in the same application. Class and its users are included in the same executter. Now we will separate classes and users to components and customers, which are located in different binaries (executables).

Although you still create a DLL for the component, its steps are very different from writing a COM component with C . You rarely involve the underlying structure. The following section describes how to build a component and how the customer uses it:

. Build a component

. Compile component

. Create a simple client application

8.1.1 Building a component

Because I am using a model fan, I decided to create a related web class to make it easy for you to use. It returns a web page and stores in a string variable for later reuse. All of these writes are referred to the help documentation of .NET FRAMWORK.

Class name RequestWebPage; it has two constructor, one attribute, and a method. The attribute is named URL, and it stores the web address of the web page, and returned by the method getContent. This method has made all your work (see Listing 8.1).

Listing 8.1 RequestWebPage class for returning from the web server back HTML

1: USING System;

2: USING SYSTEM.NET;

3: using system.io;

4: using system.text;

5:

6: Public Class RequestWebPage

7: {

8: private const Int buffer_size = 128;

9: private string m_strull;

10:

11: Public RequestWebPage ()

12: {

13:}

14:

15: Public RequestWebPage (String Strurl)

16: {

17: m_strurl = StrURL;

18:}

19:

20: Public String URL

twenty one: {

22: Get {return m_strurl;}

23: Set {m_strurl = value;

twenty four: }

25: Public void getContent (Out string strcontent)

26: {

27: // Check URL

28: IF (m_strurl == "")

29: throw new argumentexception ("URL Must Be providesd.");

30:

31: WebRequest therequest = (WebRequest) WebRequestFactory.create (m_strurl);

32: WebResponse aresponse = therequest.getResponse ();

33:

34: // Give the response to set byte buffers

35: int BytesRead = 0;

36: BYTE [] buffer = new byte [buffer_size];

37:

38: stream responsestream = theresponse.getresponsestream ();

39: BytesRead = responsestream.read (buffer, 0, buffer_size); 40:

41: // Use StringBuilder to accelerate the allocation process

42: StringBuilder strresponse = new stringbuilder ("");

43: While (bytesRead! = 0)

44: {

45: Strresponse.Append (Encoding.ascii.getstring (buffer, 0, bytesread);

46: BytesRead = responsestream.read (buffer, 0, buffer_size);

47:}

48:

49: // Give the output parameters

50: strcontent = strretponse.tostring ();

51:}

52:}

This should use the non-parameter constructor to complete the work, but I decided to initialize the URL in the constructor, which may be useful. When it is later decided to change the URL - to return the second web page, for example, the GET and SET access flags through the URL attribute make it disclosed.

Interesting thread starts at the getContent method. First, the code is a very simple check to the URL. If it is not suitable, it will trigger an argumentexception exception. After that, I asked WebRequestFactory to create a WebRequest object based on the URL passed to it.

Because I don't want to send cookies, add-end and inquiry strings, I will immediately visit WebResponse. If you need to request any of the above functions, you must implement them before this.

A byte buffer is initialized in line 35 and 36 that is used to read data from the response stream. Temporarily ignore the StringBuilder class, as long as there is data to be read in the response, the While loop will simply repeat. The final read operation will return zero, so the cycle is ended.

Now I want to go back to the StringBuilder class. Why use this class of instances instead of simply merge the byte buffer to a string variable? Look below:

Strmystring = strmystring "some more text";

It is clear here that you are copying the value. The constant "Some More Text" is fed into a string variable type and created a new string variable according to the addition operation. Then it was assigned to strmystring. There are many copies, is it?

But you may argue

Strmystring = "Some more text";

Don't show off this behavior. Sorry, for C # this is a wrong answer. It is running the same as the described assignment operation.

An additional way to this problem is to use the StringBuilder class. It uses a buffer to work, then you have added, insert, delete, and replace the operation without the copy behavior that I will have. That's why I use it in the class to merge those content in the buffer.

The buffer has led me to the last important code snippet in this class. It only involves me to get the requested character set.

Finally, when all content is read and converted, I explicitly request a string object from StringBuilder and assign it to the output variable. A return value will still cause additional copy operations.

8.1.2 Compile Components

So far, what you do is preparing a class in the internal application of the normal application. The difference is the compilation process. You have to create a library instead of an application: csc /r:system.net.dll / t: library /out:wrq.dll WebRequest.cs

Compilation Switch / T: Library tells the C # compiler, to create a library rather than searching for a static main method. Similarly, because I am using the System.Net namespace, I must reference (/ R :) Its library, this library is system.net.dll.

Your library name is WRQ.dll, now it is ready for a client application. Because I only use private components in this chapter, you don't have to copy the library to a special location, but copy to the client application directory.

8.1.3 Creating a simple client application

When a component is written and successfully compiled, what you have to do is to use it in the client application. I once again created a simple command line application, it returned the home page of the development site I maintained (see Listing 8.2).

Listing 8.2 Returns a simple web page with the RequestWebPage class

1: USING System;

2:

3: Class TestWebreq

4: {

5: public static void main ()

6: {

7: RequestWebPage WRQ = New RequestWebPage ();

8: wrq.url = "http://www.alphasierrapapa.com/iisdev/";

9:

10: String strresult;

11: TRY

12: {

13: Wrq.getContent (Out strresult);

14:}

15: Catch (Exception E)

16: {

17: Console.WriteLine (e);

18: Return;

19:}

20:

21: Console.WriteLine (Strresult);

twenty two: }

twenty three: }

Note that I have already included the call to getContent in a try catch statement. One reason is that getContent may trigger an argumentException exception. In addition, I can trigger an exception in the .NET FRAMWORK class called inside the component. Because I can't handle these anomalies within the category, I have to handle them here.

The rest of the code is just a simple component usage - call the standard constructor, access a property, and perform a method. But wait now: You need to pay attention to when compiling applications. Be sure to tell the compiler, let it quote your new component library DLL:

CSC /R :Wrq.dll WRCLIENT.CS

Everything is ready, you can test the program. The output will scroll up, and you can see the application work. Using regular expressions, you can also add code to resolve the return HTML and extract information according to your personal preferences. I expected to use this new version of SSL (Secure Socket Layer) for online credit card verification in the ASP web page.

You may notice that there is no special using statement for the library you created. The reason is that you did not define the namespace in the source file of the component.

8.2 Using the namespace work

You often use the namespace, such as System and System.net. C # uses the namespace to organize the program, and the organization's hierarchical features make the element's element to another program becomes easier. Even if the namespace are not used for external description, they are also a good way to organize applications.

Although not forced, you always have a name space to clearly identify the hierarchy of the application. .NET FRAMWORK will give a good idea to build this hierarchy. The following code snippet shows the declaration of the simple namespace in the C # original file: "

Namespace my.test

{

// Anything here belongs to the name space

}

When you access an element in the namespace, it is also necessary to use the namespace identifier to fully qualify it, or use the USING flag to introduce all members into your current namespace. The example in front of this book demonstrates how to apply these technologies.

Only a few words about accessing secure before starting using the namespace. If you don't add a specific access modifier, all types will be default to Internal. Use public when you want to access this type from the outside. Other modifiers are not allowed.

This is about the theory of full namespace. Let us continue to implement this theory - how to use the namespace when building component applications

. Packaging in the namespace

. Use the namespace in the customer application

. Add multiple classes for named space

8.2.1 Packaging in the namespace

Since you know the theoretical meaning of the namespace, let us implement it in real life. In this example, the naturally selected namespace, the naturally selected name is presenting.csharp. In order not to make you bored, just pack the RequestWebPage into Presenting.csharp, I decided to write a class for WHOIS lookup (see Listing 8.3).

Listing 8.3 Implementing WHOISLOOKUP classes in the namespace

1: USING System;

2: using system.net.sockets;

3: using system.io;

4: using system.text;

5:

6: Namespace Presenting.csharp

7: {

8: Public Class Whoislookup

9: {

10: Public Static Bool Query (String StrDomain, Out String Strwhoisinfo)

11: {

12: const Int buffer_size = 128;

13:

14: if ("== strdomain)

15: throw new argumentexception ("You Must Specify A Domain Name);

16:

17: TcpClient TCPC = New TcpClient ();

18: strwhoisinfo = "n / a";

19:

20: // Try to connect to the Whois server

21: IF (TCPC.Connect ("Whois.Networksolutions.com", 43)! = 0)

22: Return False;

twenty three:

24: // Get flow

25: stream s = tcpc.getStream ();

26:

27: // Send a request

28: STRDOMAIN = "/ r / n";

29: Byte [] BDOMARR = Encoding.ascii.getbytes (STRDOMain.TOCHARRAY ());

30: S.Write (BDOMARR, 0, STRDOMAIN.LENGTH);

31:

32: BYTE [] Buffer = New byte [buffer_size];

33: StringBuilder strwhoisresponse = new stringbuilder (""); 34:

35: int BytesRead = S.Read (buffer, 0, buffer_size);

36: While (bytesRead! = 0)

37: {

38: StrwhoisResponse.Append (Encoding.ascii.getstring (buffer, 0, bytesread);

39: BytesRead = S. Read (buffer, 0, buffer_size);

40:}

41:

42: tcpc.close ();

43: strwhoisinfo = strwhoisresponse.tostring ();

44: Return True;

45:}

46:}

47:}

The name space is declared in Chain 6, and it hurts the Whoislookup class with the pheashed arc of line 7 and 47. To declare your new namespace, it is actually what you want to do.

In the Whoislookup class, there is of course some interesting code, especially it illustrates Socket programming, using C #. After the "non-empty" domain name inspection in the Static Query method, I instant an object of the TCPClient type that is used to complete all the communication on the 43 port occupied by the Whois server. Server connection is established on line 21:

IF (TCPC.Connect ("Whois.Networksolutions.com", 43)! = 0)

Because the connection failure is expected, this method cannot trigger an exception. (You also remember the "want" and "don't" not "?) Return to a non-zero value is an error code, and return zero means the connection is successful.

For WHOIS lookup, I must first issue some information to the server - I want to find the domain name. To complete this job, first get a bidirectional stream referenced to the current TCP connection (25th line). Then, an entered / backwline pair is attached after the domain name, indicating the end of the query. Re-package, send a request (line 30) to the WHOIS server.

The remaining code and the RequestWebPage class are extremely similar. In this class, I use a buffer to read the response from the remote server. When the buffer is completed, the connection is disconnected. The returned response is transferred to the caller. The reason I am explicitly calling the close method is that I don't want to wait for the garbage collector to destroy the connection. Don't be too long connected to avoid this rare resource for TCP ports.

Before you can use the class in the .NET component, you must compile it as a library. Although there is now a defined namespace, the compile command still has no change:

CSC /R: System.Net.dll / T: library /out:whois.dll Whois.cs

Note that if you want the library to name the same method as the C # source file, there is no need to specify / out: Switch. It is specified that the switch is a good habit because many projects do not consist only by a single source file. If you specify multiple source files, the library is named in the list.

8.2.2 Using the namespace in the client application

Since you use the namespace development component, the customer also introduces the namespace.

Using presenting.csharp;

Or use a member in the namespace to use a full qualified name, for example

Presenting.csharp.Whoislookup.Query (...);

If you don't expect the conflict between the elements introduced in the namespace, the USING flag is preferred, especially when you have few types. The samples of the client are given in Listing 8.4. Listing 8.4 Test Whoislookup Components

1: USING System;

2: using presenting.csharp;

3:

4: Class TestWhois

5: {

6: public static void main ()

7: {

String strresult;

9: Bool BreturnValue;

10:

11: TRY

12: {

13: BreturnValue = WHOISLOOKUP.QUERY ("Microsoft.com", Out Strresult;

14:}

15: Catch (Exception E)

16: {

17: Console.WriteLine (e);

18: Return;

19:}

20: IF (BreturnValue)

21: Console.WriteLine (Strresult);

22: Else

23: Console.writeline ("Could Not Obtain Information from Server.");

twenty four: }

25:}

Line 2 uses the USING logo to introduce the presenting.csharp namespace. Now, I can ignore the fully qualified name of the namespace whenever I quote WHOISLOOKUP.

The program is a WHOIS lookup to the Microsoft.com field - you can also use your own domain name to replace Microsoft.com. Allow command line parameters to transfer domain names, allowing customers to make customers more wide. Listing 8.5 implements this feature, but it does not implement appropriate exception processing (in order to make the program shorter).

Listing 8.5 Transfer command line parameters to Query method

1: USING System;

2: using presenting.csharp;

3:

4: Class Whoisshort

5: {

6: public static void main (string [] args)

7: {

String strresult;

9: Bool BreturnValue;

10:

11: BreturnValue = WHOISLOOKUP.QUERY (args [0], out strresult);

12:

13: IF (BreturnValue)

14: console.writeLine (Strresult);

15: Else

16: console.writeline ("Lookup Failed.");

17:}

18:}

What you have to do is compiling this app:

CSC /R :Whois.dll Whoisclnt.cs

The application can then be executed using the command line parameter. For example, execute with the parameter of the microsoft.com

Whoisclnt Microsoft.com

When the query is running successfully, the registration information of Microsoft.com will appear. (Listing 8.6 shows a brief version of the output) This is a very convenient applet, which is not more than an hour through the components. How long does it take to write with C ? Very fortunate, I can't think of how long it takes when I use C in the first time.

Listing 8.6 WHOIS information about Microsoft.com (Simple)

D: / Csharp / Samples / Namespace> Whoisclient ...

Registrant:

Microsoft Corporation (Microsoft-DOM)

1 Microsoft Way

Redmond, WA 98052

US

Domain name: Microsoft.com

Administrative Contact:

Microsoft Hostmaster (MH37-ORG) msnhst@microsoft.com

Technical Contact, Zone Contact:

MSN NOC (mn5-org) msnnoc@microsoft.com

Billing Contact:

Microsoft-InterniC Billing Issues (mdb-org) msnbill@microsoft.com

Record Last Updated on 20-May-2000.

Record Expires On 03-MAY-2010.

Record CREATED ON 02-May-1991.

Database Last Updated on 9-Jun-2000 13:50:52 EDT.

Domain Servers In Listed Order:

ATBD.MICROSOFT.COM 131.107.1.7

DNS1.MICROSOFT.COM 131.107.1.240

DNS4.CP.MSFT.NET 207.46.138.11

DNS5.cp.msft.net 207.46.138.12

8.2.3 Increase multiple classes to name space

What is the wonderful of the WHOISLOOKUP and the RequestWebPage class to the same name space. Since WHOISLOOKUP is part of the namespace, you only have to make the RequestWebPage class also become part of the namespace.

The necessary changes are easily applied. You only need to use the namespace to encapsulate the RequestWebPage class:

Namespace Presenting.csharp

{

Public Class RequestWebPage

{

...

}

}

Although two classes are included in two different files, they are part of the same namespaces after compiling:

CSC /R :System.net.dll / T: library /out:presenting.csharp.dll Whois.cs WebRequest.cs

You don't have to name the DLL in the name of the name space. However, this will help you easily remember, which library is to be referenced when compiling a client application.

8.3 small knot

In this chapter, you learned how to build a component that can be used in the customer program. Initially, you don't have to care about the namespace, but this feature is introduced in the second component. Name spaces are an excellent approach to organize applications.

The components in the C # are easily created, and as long as the libraries and applications are copied in the same directory, you don't even have to install it. When you want to create a class library that must be used by multiple customers, the steps have changed - and the next chapter will tell you why.

转载请注明原文地址:https://www.9cbs.com/read-810.html

New Post(0)