Professional ASP.NET 3.5 in C# and Visual Basic Part 135 pot

10 213 0
Professional ASP.NET 3.5 in C# and Visual Basic Part 135 pot

Đang tải... (xem toàn văn)

Thông tin tài liệu

Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1303 Chapter 28: Using Business Objects Runtime Callable Wrapper (RCW) .NET Code (C# or VB.NET) ActiveX DLL or OCX (COM Component) Your New .NET Code .NETs Built-In Interoperability Technology Your existing ActiveX Component Code Managed Code Unmanaged Code Figure 28-6 The Runtime Callable Wrapper The Runtime Callable Wrapper, or RCW, is the magic piece of code that enables interaction to occur between .NET and COM. One RCW is created for each COM component in your project. To create an RCW for a COM component, you can use Visual Studio 2008. To add an ActiveX DLL to the References section of your project, choose Website ➪ Add Reference or choose the Add Reference menu item that appears when you right-click the root node of your project in the Solution Explorer. The Add Reference dialog box appears with five tabs: .NET, COM, Projects, Browse, and Recent, as shown in Figure 28-7. For this example, select the COM tab and locate the component that you want to add to your .NET project. After you have located the component, highlight the item and click OK to add a reference to the component to your project. The newly added component will then be found inside a newly created Bin folder in your project. Your Interop library is automatically created for you from the ActiveX DLL that you told Visual Studio 2008 to use. This Interop library is the RCW component customized for your ActiveX control, as shown previously in Figure 28-6. The name of the Interop file is simply Interop.OriginalName.DLL . It is also possible to create the RCW files manually instead of doing it through Visual Studio 2008. In the .NET Framework, you will find a method to create RCW Interop files for controls manually through a command-line tool called the Type Library Importer. You invoke the Type Library Importer by using the tlbimp.exe executable. For example, to create the Interop library for the SQLDMO object used earlier, start up a Visual Studio 2008 Command Prompt from the Microsoft Visual Studio 2008 ➪ Visual Studio Tools group within your Start Menu. From the comment prompt, type tlbimp sqldmo.dll /out:sqldmoex.dll In this example, the /out: parameter specifies the name of the RCW Interop library to be created. If you omit this parameter, you get the same name that Visual Studio would generate for you. 1303 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1304 Chapter 28: Using Business Objects Figure 28-7 The Type Library Importer is useful when you are not using Visual Studio 2008 as your development environment, if you want to have more control over the assemblies that get created for you, or if you are automating the process of connecting to COM components. The Type Library Importer is a wrapper application around the TypeLibConvertor class of the Sys- tem.Runtime.InteropServices namespace. Using COM Objects in ASP.NET Code To continue working through some additional examples, you next take a look at a simple example of using a COM object written in Visual Basic 6 within an ASP.NET page. In the first step, you create an ActiveX DLL that you can use for the upcoming examples. Add the Visual Basic 6 code shown in Listing 28-1 to a class called NameFunctionsClass and compile it as an ActiveX DLL called NameComponent.dll . Listing 28-1: VB6 code for ActiveX DLL, NameComponent.DLL Option Explicit Private m_sFirstName As String Private m_sLastName As String Public Property Let FirstName(Value As String) m_sFirstName = Value 1304 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1305 Chapter 28: Using Business Objects End Property Public Property Get FirstName() As String FirstName = m_sFirstName End Property Public Property Let LastName(Value As String) m_sLastName = Value End Property Public Property Get LastName() As String LastName = m_sLastName End Property Public Property Let FullName(Value As String) m_sFirstName = Split(Value, " ")(0) If (InStr(Value, " ") > 0) Then m_sLastName = Split(Value, " ")(1) Else m_sLastName = "" End If End Property Public Property Get FullName() As String FullName = m_sFirstName + " " + m_sLastName End Property Public Property Get FullNameLength() As Long FullNameLength = Len(Me.FullName) End Property Now that you have created an ActiveX DLL to use in your ASP.NET pages, the next step is to create a new ASP.NET project using Visual Studio 2008. Replace the HTML code in the Default.aspx file with the HTML code illustrated in Listing 28-2. This adds a number of text boxes and labels to the HTML page, as well as the Visual Basic or C# code for the functionality. Listing 28-2: Using NameComponent.dll VB <%@ Page Language="VB" %> <script runat="server"> Protected Sub AnalyzeName_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Dim Name As New NameComponent.NameFunctionsClass() If (FirstName.Text.Length > 0) Then Name.FirstName = FirstName.Text End If If (LastName.Text.Length > 0) Then Continued 1305 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1306 Chapter 28: Using Business Objects Name.LastName = LastName.Text End If If (FullName.Text.Length > 0) Then Name.FullName = FullName.Text End If FirstName.Text = Name.FirstName LastName.Text = Name.LastName FullName.Text = Name.FullName FullNameLength.Text = Name.FullNameLength.ToString End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Using COM Components</title> </head> <body> <form id="form1" runat="server"> <p> <asp:Label ID="Label1" runat="server">First Name:</asp:Label> &nbsp; <asp:TextBox ID="FirstName" runat="server"></asp:TextBox> </p> <p> <asp:Label ID="Label2" runat="server">Last Name:</asp:Label> &nbsp; <asp:TextBox ID="LastName" runat="server"></asp:TextBox> </p> <p> <asp:Label ID="Label3" runat="server">Full Name:</asp:Label> &nbsp; <asp:TextBox ID="FullName" runat="server"></asp:TextBox> </p> <p> <asp:Label ID="Label4" runat="server">Full Name Length:</asp:Label> &nbsp; <asp:Label ID="FullNameLength" runat="server" Font-Bold="True">0</asp:Label> </p> <p> <asp:Button ID="AnalyzeName" runat="server" OnClick="AnalyzeName_Click" Text="Analyze Name"></asp:Button> </p> </form> </body> </html> C# <%@ Page Language="C#" %> <script runat="server"> 1306 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1307 Chapter 28: Using Business Objects protected void AnalyzeName_Click(object sender, System.EventArgs e) { NameComponent.NameFunctionsClass Name = new NameComponent.NameFunctionsClass(); if (FirstName.Text.Length > 0) { string firstName = FirstName.Text.ToString(); Name.set_FirstName(ref firstName); } if (LastName.Text.Length > 0) { string lastName = LastName.Text.ToString(); Name.set_LastName(ref lastName); } if (FullName.Text.Length > 0) { string fullName = FullName.Text.ToString(); Name.set_FullName(ref fullName); } FirstName.Text = Name.get_FirstName(); LastName.Text = Name.get_LastName(); FullName.Text = Name.get_FullName(); FullNameLength.Text = Name.FullNameLength.ToString(); } </script> Now you need to add the reference to the ActiveX DLL that you created in the previous step. To do so, follow these steps: 1. Right-click your project in the Solution Explorer dialog. 2. Select the Add Reference menu item. 3. In the Add Reference dialog box, select the fourth tab, Browse. 4. Locate the NameComponent.dll object by browsing to its location. 5. Click OK to add NameComponent.dll to the list of selected components and close the dialog box. If you are not using Visual Studio 2008 or code-behind pages, you can still add a reference to your COM control by creating the RCW manually using the Type Library Converter and then placing an Imports statement (VB) or using statement (C#) in the page. After you have selected your component using the Add Reference dialog, an RCW file is created for the component and added to your application. That’s all there is to it! Simply run the application to see the COM interoperability layer in action. Figure 28-8 shows the ASP.NET page that you created. When the Analyze Name button is clicked, the fields in the First Name, Last Name, and Full Name text boxes are sent to the RCW to be passed to 1307 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1308 Chapter 28: Using Business Objects the NameComponent.DLL ActiveX component. Data is retrieved in the same manner to repopulate the text boxes and to indicate the length of the full name. Figure 28-8 Accessing Tricky COM Members in C# Sometimes, some members of COM objects do not expose themselves properly to C#. In the preceding examples, the String properties did not expose themselves, but the Long property ( FullNameLength )did. You know when there is a problem because, although you can see the property, you cannot compile the application. For instance, instead of the code shown in Listing 28-2 for C#, use the following piece of code to set the FirstName property of the NameComponent.dll ActiveX component: if (FirstName.Text.Length > 0) Name.FirstName = FirstName.Text.ToString(); When you try to compile this code, you get the following error: c: \ inetpub \ wwwroot \ wrox \ Default.aspx.cs(67): Property, indexer, or event ’FirstName’ is not supported by the language; try directly calling accessor methods ’NameComponent .NameFunctionsClass.get_FirstName()’ or ’NameComponent.NameFunctionsClass .set_FirstName(ref string)’ The FirstName property seems to be fine. It shows up in IntelliSense, but you can’t use it. Instead, you must use set_FirstName (and get_FirstName to read). These methods do not show up in IntelliSense, but rest assured, they exist. 1308 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1309 Chapter 28: Using Business Objects Furthermore, these methods expect a ref string parameter rather than a String .Intheexamplefrom Listing 28-2, two steps are used to do this properly. First, String is assigned to a local variable, and then the variable is passed to the method using ref . Releasing COM Objects Manually One of the great things about .NET is that it has its own garbage collection — it can clean up after itself. This is not always the case when using COM interoperability, however. .NET has no way of knowing when to release a COM object from memory because it does not have the built-in garbage collection mechanism that .NET relies on. Because of this limitation, you should release COM objects from memory as soon as possible using the ReleaseComObject class of the System.Runtime.InteropServices.Marshal class: C# System.Runtime.InteropServices.Marshal.ReleaseComObject(Object); It should be noted that if you attempt to use this object again before it goes out of scope, you would raise an exception. Error Handling Error handling in .NET uses exceptions instead of the HRESULT values used by Visual Basic 6 applica- tions. Luckily, the RCW does most of the work to convert between the two. Take, for instance, the code shown in Listing 28-3. In this example, a user-defined error is raised if the numerator or the denominator is greater than 1000. Also notice that we are not capturing a divide-by-zero error. Notice what happens when the ActiveX component raises the error on its own. Begin this example by compiling the code listed in Listing 28-3 into a class named DivideClass within an ActiveX component called DivideComponent.dll . Listing 28-3: Raising errors in VB6 Public Function DivideNumber(Numerator As Double, _ Denominator As Double) As Double If ((Numerator > 1000) Or (Denominator > 1000)) Then Err.Raise vbObjectError + 1, _ "DivideComponent:Divide.DivideNumber", _ "Numerator and denominator both have to " + _ "be less than or equal to 1000." End If DivideNumber = Numerator / Denominator End Function Next, create a new ASP.NET project; add a reference to the DivideComponent.dll (invoking Visual Studio 2008 to create its own copy of the RCW). Remember, you can also do this manually by using the tlbimp executable. 1309 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1310 Chapter 28: Using Business Objects Now add the code shown in Listing 28-4 to an ASP.NET page. Listing 28-4: Error handling in .NET VB <%@ Page Language="VB" %> <script runat="server"> Protected Sub Calculate_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Dim Divide As New DivideComponent.DivideClass() Try Answer.Text = Divide.DivideNumber(Numerator.Text, Denominator.Text) Catch ex As Exception Answer.Text = ex.Message.ToString() End Try System.Runtime.InteropServices.Marshal.ReleaseComObject(Divide) End Sub </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Using COM Components</title> </head> <body> <form id="form1" runat="server"> <p> <asp:Label ID="Label1" runat="server">Numerator:</asp:Label> &nbsp; <asp:TextBox ID="Numerator" runat="server"></asp:TextBox> </p> <p> <asp:Label ID="Label2" runat="server">Denominator:</asp:Label> &nbsp; <asp:TextBox ID="Denominator" runat="server"></asp:TextBox> </p> <p> <asp:Label ID="Label3" runat="server"> Numerator divided by Denominator:</asp:Label> &nbsp; <asp:Label ID="Answer" runat="server" Font-Bold="True">0</asp:Label> </p> <p> <asp:Button ID="Calculate" runat="server" OnClick="Calculate_Click" Text="Calculate"> </asp:Button> </p> 1310 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1311 Chapter 28: Using Business Objects </form> </body> </html> C# <%@ Page Language="C#" %> <script runat="server"> protected void Calculate_Click(object sender, System.EventArgs e) { DivideComponent.DivideClass myDivide = new DivideComponent.DivideClass(); try { double numerator = double.Parse(Numerator.Text); double denominator = double.Parse(Denominator.Text); Answer.Text = myDivide.DivideNumber(ref numerator, ref denominator).ToString(); } catch (Exception ex) { Answer.Text = ex.Message.ToString(); } System.Runtime.InteropServices.Marshal.ReleaseComObject(myDivide); } </script> The code in Listing 28-4 passes the user-entered values for the Numerator and Denominator to the DivideComponent.dll ActiveX component for it to divide. Running the application with invalid data gives the result shown in Figure 28-9. Figure 28-9 1311 Evjen c28.tex V2 - 01/28/2008 3:52pm Page 1312 Chapter 28: Using Business Objects Depending on the language that you are using to run the ASP.NET application, you will see different values for different sets of data. For valid inputs, you will always see the correct result, of course, and for any input that is over 1000, you see the Visual Basic 6 appointed error description of Numerator and denominator both have to be less than or equal to 1000 . However, for invalid Strings, Visual Basic 2008 reports Cast from string "abc" to type ‘Double’ is not valid. whereas C# reports Input string was not in a correct format. . For a divide by zero, they both report Divide by Zero because the error is coming directly from the Visual Basic 6 runtime. Deploying COM Components with .NET Applications Deploying COM components with your .NET applications is very easy; especially when compared to just deploying ActiveX controls. Two scenarios are possible when deploying .NET applications with COM components: ❑ Using private assemblies ❑ Using shared assemblies Private Assemblies Installing all or parts of the ActiveX component local to the .NET application is considered installing private assemblies. In this scenario, each installation of your .NET application on the same machine has, at least, its own copy of the Interop library for the ActiveX component you are referencing, as shown in Figure 28-10. Interop.MyCOM.dllMyApp.exe C:\Program Files\First Application Location\ Interop.MyCOM.dllMyApp.exe C:\Program Files\Second Application Location\ MyCOM.DLL C:\Program Files\Third Party COM Controls\ (Managed Code) (RCW) (Managed Code) (RCW) (ActiveX DLL) Figure 28-10 It is up to you whether you decide to install the ActiveX component as local to the application or in a shared directory for all calling applications. It was once considered proper practice to separate ActiveX components into their own directory so that if these components were referenced again by other applications, you did not have to register or install the 1312 . 01/28/2008 3: 52 pm Page 130 3 Chapter 28: Using Business Objects Runtime Callable Wrapper (RCW) .NET Code (C# or VB .NET) ActiveX DLL or OCX (COM Component) Your New .NET Code .NETs Built -In Interoperability Technology Your. Objects in ASP. NET Code To continue working through some additional examples, you next take a look at a simple example of using a COM object written in Visual Basic 6 within an ASP. NET page. In the. use in your ASP. NET pages, the next step is to create a new ASP. NET project using Visual Studio 2008. Replace the HTML code in the Default.aspx file with the HTML code illustrated in Listing 28-2.

Ngày đăng: 05/07/2014, 19:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan