Using Visual Basic 6 with Visual Basic .NET: COM Interop Chapter 9

ou juste avant la balise de fermeture -->

 

 

 CD ROM Annuaire d'Entreprises France prospect (avec ou sans emails) : REMISE DE 10 % Avec le code réduction AUDEN872

10% de réduction sur vos envois d'emailing --> CLIQUEZ ICI

Retour à l'accueil, cliquez ici

ou juste avant la balise de fermeture -->

Voir également :

 

 

175 Using Visual Basic 6 with Visual Basic .NET: COM Interop This chapter focuses on making your Visual Basic 6 and Visual Basic .NET applications work together. The mechanism that makes interoperability between the two products possible is known as COM interop. We’ll start by looking at the various ways you can create or use existing components that communicate across COM and .NET component boundaries. We’ll also show you how to debug across calls between Visual Basic 6 and Visual Basic .NET authored components. Finally, we’ll discuss the role of binary compatibility in Visual Basic .NET. If you’ve been creating multitiered applications using Visual Basic 6, your application has likely evolved into a large system spanning multiple components. Let’s say, for example, that you have an application composed of a Visual Basic standard EXE front end containing ActiveX controls talking to a middletier Visual Basic DLL. The Visual Basic DLL in turn talks to a back-end SQL Server database. Upgrading such an application to Visual Basic .NET in one shot is nearly impossible. This is where COM interop swoops in to save the day. COM interop allows you to upgrade one component at a time while keeping the system alive. For example, you can upgrade your Visual Basic 6 middletier component to Visual Basic .NET independently of the user interface (UI) C0961587x.fm Page 175 Thursday, November 15, 2001 3:33 PM 176 Part II Upgrading Applications component. Once you have tested your new Visual Basic .NET component with your Visual Basic 6 UI client, you can update the client to take advantage of the new Visual Basic .NET server component. At a later date you may decide to upgrade your Visual Basic 6 client components to Visual Basic .NET components. An ActiveX control vendor may offer a .NET upgrade to your favorite ActiveX control, leading you to replace all ActiveX versions of the control in your application with the .NET version. Eventually your entire system evolves to .NET, smoothly and without interruption. Visual Studio .NET Is Built on COM Interop You do not need to look far for an example of COM interop at work. If you’re running Visual Studio .NET, COM interop is right under your nose. The Property Browser is written in C#, a language built on the .NET Framework. Most of the designers you will find, such as the Windows Forms designer, are written in a language supported by .NET. All of the wizards are written in either C# or Visual Basic .NET. The Visual Studio .NET environment is a traditional client application written in C++ that interoperates with these other .NET components using COM interop. The Upgrade Wizard relies heavily on COM interop to accomplish its tasks. The wizard is a .NET component that calls out to the upgrade engine, an out-of-process COM EXE server, to upgrade your Visual Basic 6 project. The upgrade engine in turn calls back to the wizard to provide status. As your application is being upgraded, the status text and progress bar updates you see are brought to you by way of COM interop. We look forward to the day when 100 percent of our Visual Studio .NET components are written in Visual Basic .NET. Until that day, COM interop will be silently at work keeping Visual Studio .NET humming along. It would be nice to be able to upgrade your entire application to .NET, but in some cases it may not be feasible. For example, what if your application relies on a COM component for which there is no .NET equivalent? A good example is a Visual Basic 6 ActiveX document or DHTML page designer for which there is no equivalent component in .NET. In such cases COM interop can help keep things running without hindering you from moving other parts of your system forward to Visual Basic .NET. C0961587x.fm Page 176 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 177 Although we’ve been talking about interoperation among Visual Basic components, the concept of interoperation applies to all COM components. For example, your application may be composed of a Visual Basic front end talking to a C++ authored middle-tier component. As long as the components that make up your application are based on COM, your Visual Basic .NET application can continue to talk to them. Similarly, your Visual Basic 6 application can continue to talk to a .NET component—authored in any language supported by .NET—as if it were a COM component, without any changes in your Visual Basic 6 application. Where COM Interop Comes into Play There are three common situations in which you will encounter COM interop: when using ActiveX controls, when calling a COM component from a .NET application or component, and when calling a .NET component from a COM application or component. Let’s take a look at each of these situations. ActiveX Controls Visual Basic .NET allows you to place either .NET or ActiveX controls on a Windows form. Chapter 13covers ActiveX control hosting in more detail. Suffice it to say that the way you use ActiveX controls in Visual Basic .NET is nearly identical to the way you use them in Visual Basic 6. You add the control to the Toolbox, place the control on the form, set design-time property values, and then write code behind it. No sweat. Communication Between a .NET Client and a COM Server Component The .NET Framework enables .NET clients to communicate with COM components. It accomplishes this by wrapping the COM component in a runtime callable wrapper (RCW) to make it look like a .NET component, as illustrated in Figure 9-1. Exposing a COM component for use with .NET requires no additional work. You simply add the COM component as a reference, and Visual Studio .NET takes care of generating the RCW for you. Later in this chapter, we demonstrate how to call a COM server from a .NET Web application. C0961587x.fm Page 177 Thursday, November 15, 2001 3:33 PM 178 Part II Upgrading Applications F09km01 Figure 9-1 Runtime callable wrapper that enables a COM component to look like a .NET component. Communication Between a COM Client and a .NET Server Component In addition to allowing .NET clients to communicate with COM components, the .NET Framework allows COM applications to communicate with .NET components by making a .NET component look like a COM component. It accomplishes this by creating a wrapper around the .NET component called a COM callable wrapper (CCW), as illustrated in Figure 9-2. To expose a .NET component to COM, you must register your .NET component as being COM callable. Visual Studio .NET provides a way for .NET components to be registered automatically for COM. The next section demonstrates how to upgrade a Visual Basic 6 component to .NET and then expose that .NET component to COM. F09km0 Figure 9-2 COM callable wrapper that enables a .NET component to look like a COM component. Upgrading a Visual Basic 6 Client/Server Application Suppose you have a Visual Basic 6 ActiveX DLL that acts as a language translator, translating a phrase in one language to another language. Your component is currently limited to rudimentary Spanish. The companion CD includes two Visual Basic 6 sample applications: TranslatorServer and TranslatorClient. In the following section we will demonstrate how to call the TranslatorServer compo-                         C0961587x.fm Page 178 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 179 nent from a Visual Basic .NET client application. First, however, you need to build the Visual Basic 6 server component by following these steps: 1. Run Visual Basic 6. 2. Open TranslatorServer.Vbp provided on the companion CD. 3. Open TranslatorServer.Cls, and you will find that it contains the following code: Public Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) As String ‘ Note to self: Find someone who speaks Spanish and VB who ‘ is willing to expand this component to translate any ‘ common English phrase If LCase(LanguageFrom) = “english” And _ LCase(LanguageTo) = “spanish” Then Select Case LCase(SentenceFrom) Case “hello world" Translate = “hola mundo" End Select End If End Function 4. From the File menu, choose Make TranslatorServer.dll and make the .DLL file into a directory on your hard drive. To test your application in Visual Basic 6, run Visual Basic 6 and open the Visual Basic 6 TranslatorClient application provided on the companion CD. Open Module1.Bas and you’ll find the following code to call the TranslatorServer component. Sub Main() Dim Translation As String Dim Ts As New TranslatorServer.Translator Translation = Ts.Translate(“hello world", “English", “Spanish”) MsgBox Translation End Sub Now select References from the Project menu, click the Browse button, and locate the TranslateServer.Dll that you built by following the previous steps. Press F5 to run the project. You should see “hola mundo” displayed, as shown in Figure 9-3. C0961587x.fm Page 179 Thursday, November 15, 2001 3:33 PM 180 Part II Upgrading Applications F09km03 Figure 9-3 “Hola mundo” translation successfully received from Visual Basic 6 server. You may be wondering what the point of all this is. So far, all we’ve done is call a Visual Basic 6 component from Visual Basic 6. Now, however, we’ll upgrade each component separately to see how to call a Visual Basic 6 component from Visual Basic .NET and vice versa. Finally, we’ll see how to tie the upgraded client and server components together to form a complete Visual Basic .NET solution. Creating a .NET Client That Talks to a COM Server Let’s create a .NET client that talks to a COM server. Since the whole point of Visual Studio .NET is to help you create applications quickly for the Web, let’s create a Web client that calls our COM server. You might want to do this, for example, if you have business logic stored internally—say, a Visual Basic 6 ActiveX DLL function that returns a list of your company’s products—that you want to make available for viewing by external partners or customers. 1. Run Microsoft Visual Studio .NET. 2. Choose New Project from the File menu. 3. Select Visual Basic ASP.NET Web Application, name the application MyAmazingTranslator, and click OK. C0961587x.fm Page 180 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 181 4. Right-click References on the Solution Explorer tab, and choose Add Reference. 5. Select the COM tab. 6. Select TranslatorServer from the list, and click OK. 7. Open WebForm1.aspx. 8. Drag and drop the following controls from the Toolbox to WebForm1: A Label, a TextBox, and a Button. 9. For the text of the label, enter My amazing English-to-Spanish translator. 10. For the text of Button1, enter Translate. 11. Double-click the Translate button and insert the following code in the Button1_Click event handler: Dim ts As New TranslatorServer.Translator() TextBox1.Text = ts.Translate(TextBox1.Text, “English", _ “Spanish”) 12. Choose Start from the Debug menu. 13. Type hello world into the text box, and click the button. See Figure 9-4 for an example of the output. You have now taken a simple desktop application and made it available to the world. Hola mundo indeed. F09km04 Figure 9-4 My amazing English-to-Spanish translator at work on the Web. C0961587x.fm Page 181 Thursday, November 15, 2001 3:33 PM 182 Part II Upgrading Applications Debugging Between the Visual Basic .NET Client and Visual Basic 6 Server When upgrading Visual Basic 6 code to Visual Basic .NET, it is critical that you be able to debug the changes that you made yourself or that were made by the Upgrade Wizard. The Microsoft Visual Studio .NET development environment makes it possible to debug between Visual Basic 6 applications and Visual Basic .NET. However, you need to make a few changes to your Visual Basic 6 code in order to debug it using the Visual Studio .NET debugger. Preparing Your Visual Basic 6 Project to Debug Using Visual Studio .NET To be able to set breakpoints in your Visual Basic 6 source code, you need to build your Visual Basic 6 project with debugging symbols turned on. To do so, perform the following steps: 1. Run Visual Basic 6 and load the application you want to debug. In this case, load TranslatorServer.vbp. 2. From the Project menu, choose TranslatorServer Properties. 3. Click the Compile tab and select Create Symbolic Debug Info. 4. For best results, select No Optimization. See Figure 9-5. F09km05 Figure 9-5 Recommended Visual Basic 6 options for debugging. At this point it’s a good idea to turn on binary compatibility so that you do not need to update your .NET client application. C0961587x.fm Page 182 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 183 5. Click the Component tab. 6. Change the Version Compatibility setting from Project Compatibility to Binary Compatibility, as shown in Figure 9-6. 7. Click OK to close the Project Properties dialog box. Now rebuild your application. Choose Make TranslatorServer.dll from the File menu, click OK, and click Yes to replace the existing file, if prompted to do so. F09km06 Figure 9-6 Setting binary compatibility in Visual Basic 6. Now you’re ready to debug. 1. Run Visual Studio .NET and open the MyAmazingTranslator Web project you created earlier. 2. Select the MyAmazingTranslator project in Solution Explorer. 3. From the Project menu, choose Properties. 4. Expand the Configuration Properties folder and select Debugging. 5. Under Debuggers, click Unmanaged Code Debugging. 6. Click OK to close the dialog box. 7. Open WebForm1.aspx, and double-click the Translate button. C0961587x.fm Page 183 Thursday, November 15, 2001 3:33 PM 184 Part II Upgrading Applications 8. Insert a breakpoint on the following line: TextBox1.Text = ts.Translate(TextBox1.Text, “English", _ “Spanish”) 9. From the File menu, choose Open File, and open TranslatorServer. cls, saved as part of the Visual Basic 6 TranslatorServer project. 10. Right-click the first line of code in the Translate function, and select Insert Breakpoint. 11. Choose Start from the Debug menu. 12. Click the Translate button. Execution should break on the following line: TextBox1.Text = ts.Translate(TextBox1.Text, “English", _ “Spanish”) 13. Step over the line, and execution should break in your Visual Basic 6 TranslatorServer.cls code file. You can now step through your Visual Basic 6 code to ensure that everything is working properly. Note In order to debug an ASP.NET application on your local machine, you need to be added as a member of the Debugger Users group. If you do not have administrative privileges on the machine, you also need to change the Machine.config file for Aspnet _wp.exe to run Aspnet_wp.exe with User privileges rather than System account privileges. See Visual Studio .NET’s Help system for more details. Exposing a Visual Basic .NET Component to Be Called by a Visual Basic 6 Client In some cases, you will want to upgrade your Visual Basic 6 server and make it available to your Visual Basic 6 or other COM client applications. For example, since Visual Basic .NET allows you to create multithreaded components, you may want to upgrade your Visual Basic 6 component to a .NET component. You can then register the component to take advantage of a multithreaded environment such as Microsoft Transaction Server (MTS) in order to use object pooling, for example. C0961587x.fm Page 184 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 185 Let’s take the Visual Basic 6 TranslatorServer component located on the companion CD and upgrade it to Visual Basic .NET by performing the following steps: 1. Run Visual Studio .NET. 2. From the File menu, choose Open Project and open TranslatorServer. vbp. 3. Step through the Upgrade Wizard by clicking Next and selecting the default options as you go. Let’s change the name of the .NET server so that it doesn’t conflict with the server name of its COM predecessor. 4. Select the TranslatorServer project in the Solution Explorer. 5. From the Project menu, choose Properties. 6. Change the Assembly Name from TranslatorServer to TranslatorServer. net. 7. Click OK to close the Project Properties dialog box. 8. View the code for TranslatorServer.vb: Option Strict Off Option Explicit On Public Class Translator Public Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, ByVal LanguageTo As String) _ As String ‘ Note to self: Find someone who speaks Spanish and VB ‘ who is willing to expand this component to translate ‘ any common English phrase If LCase(LanguageFrom) = “english” And _ LCase(LanguageTo) = “spanish” Then Select Case LCase(SentenceFrom) Case “hello world" Translate = “hola mundo" End Select End If End Function End Class Note that the upgraded code, specifically the contents of the Translate function, is exactly the same as the Visual Basic 6 code. The point is that you C0961587x.fm Page 185 Thursday, November 15, 2001 3:33 PM 186 Part II Upgrading Applications can create a Visual Basic .NET server in exactly the same way that you create a Visual Basic 6 ActiveX DLL server. Now for the gotcha. Although you can build the upgraded Visual Basic .NET server, you cannot call it from Visual Basic 6. Why not? Because by default a Visual Basic .NET server is meant to be called by other .NET components, not by a COM component. To call a Visual Basic .NET server from a COM application such as Visual Basic 6, you need to register the server for COM. The simple way to expose the component to COM is to turn on the Register For COM Interop attribute by doing the following: 1. Select the TranslatorServer project in the Solution Explorer. 2. From the Project menu, choose Properties. 3. Under the Configuration Properties folder, select Build. 4. Select the Register For COM Interop check box, as shown in Figure 9-7, and click OK to close the dialog box. 5. From the Build menu, choose Build Solution, and click the Save button to save the Solution file. This step creates the Visual Basic .NET DLL and also registers it for COM. F09km07 Figure 9-7 Registering the component for COM interop. Note Registering a .NET component for COM interop does not necessarily mean that only COM clients can use the component. Instead, it opens that component up to the world of both COM and .NET. Exposing your .NET server to COM allows you to upgrade old clients or to create new clients in .NET that use the COM server. At the same time you can make a quick modification to other COM clients to allow them to work with your .NET server. C0961587x.fm Page 186 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 187 Now you are ready to call the Visual Basic .NET TranslatorServer component from Visual Basic 6. This process involves the same steps used to create the Visual Basic 6 TranslatorClient application located on the companion CD. To call the Visual Basic .NET TranslatorServer component from Visual Basic .NET, follow these steps: 1. Run Visual Basic 6 and open the TranslatorClient application located on the companion CD. 2. Choose References from the Project menu. 3. Deselect TranslatorServer, the Visual Basic 6 server component. 4. Select TranslatorServer_net, the Visual Basic .NET server component. 5. Open TranslatorClient.bas. 6. Change the following declaration from Dim Ts As New TranslatorServer.Translator to Dim Ts As New TranslatorServer_net.Translator 7. Run the application. You should see the results shown in Figure 9-3. Note If you want to add features to your upgraded Visual Basic .NET component, you should add COM attributes to ensure binary compatibility. Binary compatibility causes your Visual Basic .NET component to look, act, and smell like existing COM clients no matter what new features you add to the component. If you break compatibility, your COM clients will not be able to find the .NET component. You will be forced to recompile your COM client against the updated .NET server and redistribute it. For an example of how to add COM attributes to ensure binary compatibility, see “Replacing COM with .NET: Binary Compatibility” later in this chapter. Debugging Between the Visual Basic 6 Client and .NET Server Earlier we showed you how to debug both Visual Basic 6 and Visual Basic .NET code using the Microsoft Visual Studio .NET debugger. Now we’re going to debug our Visual Basic 6 client application and .NET server, using both the C0961587x.fm Page 187 Thursday, November 15, 2001 3:33 PM 188 Part II Upgrading Applications Visual Basic 6 debugger and the Visual Studio .NET debugger to step across the call from Visual Basic 6 code to Visual Basic .NET code. Let’s start in the Visual Studio .NET development environment. 1. Run Visual Studio .NET and open the TranslatorServer application you upgraded to Visual Basic .NET earlier. 2. Open TranslatorServer.vb and place a breakpoint within the Translate function on the following line: If LCase(LanguageFrom) = “english” And _ LCase(LanguageTo) = “spanish” Then 3. Select the TranslatorServer project in Solution Explorer. 4. From the Project menu, choose Properties. 5. Under the Configuration Properties folder, select Debugging. 6. Select Start External Program, click the Browse (“…”) button, and search for VB6.exe. 7. From the Debug menu, choose Start. Visual Basic 6 will launch. 8. From Visual Basic 6, open TranslatorClient.vbp. 9. Place a breakpoint on the following line: Translation = Ts.Translate(“hello world", “English", _ “Spanish”) 10. Run the Visual Basic 6 client application. Execution will break in the Visual Basic 6 application. Step over the line of code. The Visual Studio .NET debugger will appear, and execution will break in the Visual Basic .NET server application. You can step through and debug your Visual Basic .NET server application code. When execution returns from the Visual Basic .NET server, function execution resumes in the Visual Basic 6 debugger. Pretty cool, eh? Tying It All Together As you have seen, COM interop enables you to upgrade your application one piece at a time. You can choose to upgrade one part to .NET while keeping other parts based on COM. If your goal is to move your application to the Web or an intranet environment, plenty of options are available to you. For example, you can create a Web front end that uses the same back-end logic currently in use by your traditional Windows client applications. You can also make your back-end functions—your business logic—available to remote clients on the C0961587x.fm Page 188 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 189 Internet. To do so, you can expose your functions as Web services. In the case of the Translator class, you can expose the Translate function over the Web by adding a Web service class to the project, copying the contents of the Translator class to the Web service class, and marking the Translate function as a Web- Method. We leave this task as an exercise for you to complete. Replacing COM with .NET: Binary Compatibility In creating Visual Basic versions 4, 5, and 6, the Microsoft Visual Basic development team worked hard to allow you to create Visual Basic COM components that are backward compatible. This feature was enabled by an innocentlooking check box on the Component tab of the Project Properties dialog box, shown earlier in Figure 9-6. Binary compatibility in Visual Basic 6 enabled you to create version 2 of a COM component that is a compatible replacement for version 1 of that component. What this means is that the version 2 component contains exactly the same public objects, properties, methods, and events as the version 1 component. In addition, it means that the properties, methods, and events appear in exactly the same order as in the version 1 component. The version 2 component also understands how to initialize itself using property settings saved by the version 1 component. Although the version 2 component needs to look, act, and smell like a version 1 component, the version 2 component can include additional objects, properties, and methods that improve upon the version 1 component. No matter the improvements, however, in order to keep clients of the version 1 server component working with the version 2 component, the version 2 component must expose some subset of itself as a version 1 component. If the version 2 component doesn’t expose itself as a version 1 component, you need to do one of the following: A. Invest in fixing the version 2 component to behave identically to the version 1 component and then invest further in testing the component to ensure that no existing version 1 clients are broken by the changes. B. Rename the version 2 component and change its attributes in such a way that it exposes itself as a completely new component. Clients that are using the version 1 component continue to use that component and are not disturbed by the distribution of the version 2 component. C. Recompile all clients that use the version 1 component to use the version 2 component and then distribute the client and a version 2 server component as a matched pair. C0961587x.fm Page 189 Thursday, November 15, 2001 3:33 PM 190 Part II Upgrading Applications Which option makes more sense? Option B is generally the recommended approach if you have widely distributed clients that rely on version 1 of the server component. If there is any doubt in your mind about whether you can update an existing component or create a new component as a direct replacement of a version 1 component, don’t do it. Instead, go with option B. It’s the safe bet. When it comes to creating Visual Basic .NET components that are direct replacements of your Visual Basic 6 components, Visual Basic .NET adopts the option B approach. Simply put, you can’t do it, although if the truth be told, it’s possible but not easy. You’ll sleep much better if you simply assume that you can’t directly replace a Visual Basic 6 component with a Visual Basic .NET one. The Visual Basic team deliberately chose not to include features that would make it easy for you to mark a Visual Basic .NET component as being a compatible replacement for a Visual Basic 6 component. We’ll let the following Visual Basic code speak for itself: Const Old_compiler = “VB6.EXE" Const New_compiler = “VBC.EXE" Const Old_runtime = “MSVBVM60.DLL" Const New_runtime = “.NET Framework and Microsoft.VisualBasic.Dll" If New_compiler <> Old_compiler And New_runtime <> Old_runtime Then MsgBox “Minor behavioral differences that are expensive to “ & _ “find and fix" End If Indirect Replacement Model Visual Basic .NET takes an indirect approach in creating Visual Basic .NET components that are replacements of your Visual Basic 6 COM components. This approach means that you can create a component that looks and smells like a Visual Basic .NET component but doesn’t necessarily act 100 percent like the Visual Basic 6 component it’s “replacing.” Since to take advantage of new version 2 component features you need to update your existing clients, why not live a little and roll those features into a Visual Basic .NET component? Putting the new features in a separate component has the advantage of not disturbing the version 1 component. Clients that are running against the version 1 component continue to run against it, unaffected by the changes in the version 2 component. When you are ready to move your clients to the version 2 component, you can update and redistribute them as needed. By using the Visual Basic Upgrade Wizard, you can quickly upgrade your Visual Basic 6 components to Visual Basic .NET components. Although the wizard doesn’t give you a full, 100 percent binary-compatible replacement for your C0961587x.fm Page 190 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 191 Visual Basic 6 component, what you end up with is pretty close. All properties, methods, and events are brought forward, preserving the public interface of your component. Once you have worked out all of the upgrade-related comments and issues in the upgrade report, you can effectively replace your Visual Basic 6 component with the .NET version by making a quick change to the Visual Basic 6 client application so that it uses your .NET component instead of the Visual Basic 6 component. You then need to rebuild and redeploy your Visual Basic 6 application to take advantage of the new Visual Basic .NET server component. Enabling Binary Compatibility in Visual Basic .NET Classes If you want to expose your upgraded Visual Basic .NET server component to a COM client and you plan on making changes to the Visual Basic .NET server component over time, we strongly suggest that you do the following to ensure compatibility:  Declare all the public class properties and methods in an interface.  Declare all the public events in a separate event interface.  Add attributes to the class to declare ID attributes for the class, interface, and event interface.  Change the class declaration so that it implements both the programmable and event interfaces. Let’s step through an example that demonstrates how to enable binary compatibility in a Visual Basic .NET class. Doing so will ensure that a COM client that uses the class will continue to work with it even after you have added new functionality to the class. We’ll start with a Visual Basic .NET class that was upgraded from Visual Basic 6. Assume that the filename for the class is Class1.vb. Option Strict Off Option Explicit On Public Class Translator Public Event TranslationError(ByVal ErrorMessage As String) Public Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) As String (continued) C0961587x.fm Page 191 Thursday, November 15, 2001 3:33 PM 192 Part II Upgrading Applications Dim fSuccess As Boolean ‘ Note to self: Find someone who speaks Spanish and VB who ‘ is willing to expand this component to translate any common ‘ English phrase If LCase(LanguageFrom) = “english” And _ LCase(LanguageTo) = “spanish” Then Select Case LCase(SentenceFrom) Case “hello world" Translate = “hola mundo" fSuccess = True End Select End If If Not fSuccess Then RaiseEvent TranslationError( _ “Translation not implemented for “ & SentenceFrom) End If End Function End Class 1. Choose Add New Item from the Project menu and select COM Class. This gives you a template class for creating binary compatible objects. 2. Copy and paste the public event TranslationError and the public method Translate to the new COM class. Paste the code after Sub New. 3. Right-click Class1.vb in the Solution Explorer and delete it. We no longer need it. 4. View the code for ComClass1 and expand the #Region “COM GUIDs,” since you will need to use these values later. 5. Change the Public Class declaration for ComClass1 to Translator as follows: Public Class Translator 6. Add the following Imports clause to the top of the file as follows. COM attributes such as Guid and ComVisible will come from this namespace. Imports System.Runtime.InteropServices C0961587x.fm Page 192 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 193 7. Replace the ComClass attribute in the Translator class with the following attributes: _ Public Class Translator 8. Define the programmable interface containing the Translate method. Define the interface after the #End Region for “COM GUIDs” as follows: _ Interface ITranslate _ Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) As String End Interface 9. Immediately following the programmable interface, insert the declaration for the event interface as follows: _ Interface ITranslateEvents Event TranslationError(ByVal ErrorMessage As String) End Interface 10. Add an Implements clause after the Public Class declaration to implement the programmable and event interfaces you just declared as follows: Public Class Translator Implements ITranslate, ITranslateEvents 11. Modify the Public Event declaration to implement the interface event as follows: Public Event TranslationError(ByVal ErrorMessage As String) _ Implements ITranslateEvents.TranslationError 12. Modify the public Translate method to implement the ITranslate. Translate interface method as follows: Public Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) _ As String _ Implements ITranslate.Translate C0961587x.fm Page 193 Thursday, November 15, 2001 3:33 PM 194 Part II Upgrading Applications When completed, you should have the following class with all the necessary COM attributes defined. You can rebuild the class without breaking compatibility with existing COM clients. The only way you will break compatibility is if you consciously change GUIDs, change a method or event signature, or change the order of events or methods defined in an interface. To maintain compatibility from this point on, you must restrict yourself to adding new methods to the end of an interface. You can never remove or change an existing method, nor can you can change the order of the methods. Imports System.Runtime.InteropServices _ Public Class Translator Implements ITranslate, ITranslateEvents #Region “COM GUIDs" ‘ These GUIDs provide the COM identity for this class ‘ and its COM interfaces. If you change them, existing ‘ clients will no longer be able to access the class. Const ClassId As String = “4B33F612-69C0-4270-A7F3-1B460EBDE978" Const InterfaceId As String = _ “D1C5A219-A6C9-46CA-939F-8CF2D22FE441" Const EventsId As String = “86215D08-D4AD-4CA8-9BAC-01E8A592812D" #End Region _ Interface ITranslate _ Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) As String End Interface _ Interface ITranslateEvents Event TranslationError(ByVal ErrorMessage As String) End Interface ‘ A creatable COM class must have a Public Sub New() ‘ with no parameters; otherwise, the class will not be ‘ registered in the COM registry and cannot be created ‘ via CreateObject. Public Sub New() MyBase.New() End Sub Public Event TranslationError(ByVal ErrorMessage As String) _ Implements ITranslateEvents.TranslationError C0961587x.fm Page 194 Thursday, November 15, 2001 3:33 PM Chapter 9 Using Visual Basic 6 with Visual Basic .NET: COM Interop 195 Public Function Translate(ByVal SentenceFrom As String, _ ByVal LanguageFrom As String, _ ByVal LanguageTo As String) As String _ Implements ITranslate.Translate Dim fSuccess As Boolean ‘ Note to self: Find someone who speaks Spanish and VB who ‘ is willing to expand this component to translate any common ‘ English phrase If LCase(LanguageFrom) = “english” And _ LCase(LanguageTo) = “spanish” Then Select Case LCase(SentenceFrom) Case “hello world" Translate = “hola mundo" fSuccess = True End Select End If If Not fSuccess Then RaiseEvent TranslationError( _ “Translation not implemented for “ & SentenceFrom) End If End Function End Class Note In order to control the binary compatibility of components, many of you asked for a Visual Basic feature to expose COM attributes such as Guid and method IDs in a Visual Basic class. Visual Basic 6 offers a simple way to enable binary compatibility—the Binary Compatibility option—but does not allow you to define or edit the COM attributes that it automatically generates for you. Visual Basic .NET does not offer any simple solution to binary compatibility; there is no binary compatibility option that you can turn on. Instead, you must write code manually defining the interfaces and COM attributes to enforce binary compatibility. The ability to specify COM attributes comes at a cost: more code. After you have “beautified” your code by manually adding these attributes, you may ask what you have gotten yourself into. Be careful what you ask for—particularly if you’ve requested more control in specifying COM attributes; you just might get it. C0961587x.fm Page 195 Thursday, November 15, 2001 3:33 PM 196 Part II Upgrading Applications Conclusion You can mix and match COM with .NET in any number of ways, depending on the needs of your business. There are economic and practical reasons for choosing to have one part of your application based on .NET and the other part based on COM. The beauty of COM interop is that it gives you a choice. When upgrading your applications, you don’t have to standardize on .NET immediately to take advantage of the new features. You can start using those new features now and continue to use your existing Visual Basic 6 code and components as needed to accomplish your goals more quickly and effectively. C0961587x.fm Page 196 Thursday, November 15, 2001 3:33 PM