Login | Register   
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

COM Interop: Making .NET and VFP Talk to Each Other

Whether you use a COM component from .NET or a .NET component from a COM-enabled environment (such as VFP), COM Interop is the mechanism that allows for such interoperability.


advertisement
any developers wrote VFP applications using COM components, usually for data access logic and business logic. As a VFP developer you'll be relieved to know that you can reuse those components in .NET, allowing you to easily create a .NET User Interface (a Web application, for instance) that uses those VFP components, instead of throwing them away and rewriting everything from scratch. On the other hand, the .NET Framework comes with many classes that VFP developer might want to use in their VFP applications, and that is also possible.

Whether you use a COM component from .NET, or a .NET component from a COM-enabled environment (such as VFP), COM Interop is the mechanism that allows for such interoperability.

Why COM Interop?
COM-enabled languages can use COM components created in any language because those components conform to the standards defined by COM. Most languages have different types, or treat common types in a different way, and therefore, in order to make components created in different languages talk to each other, they have to be compatible, and it is COM that determines the common rules.

.NET goes a step further in trying to address issues with the COM standards (such as DLL hell), and it uses different approaches that lead to a very different set of standards. COM components and .NET components are not compatible by default; however, keeping in mind that many companies have put a lot of work into COM components, Microsoft added a mechanism to .NET so that .NET components can see COM components as if they were .NET components, and COM components can see .NET components as if they were COM components.

Fast Facts
.NET is growing more and more important, making interoperability between .NET and VFP a hot topic. There are a few different approaches to combining the two tools, such as COM Interop, Web services, and interoperability on the database level.

Calling VFP Components from .NET
For .NET to see COM components, you must create a proxy (or wrapper). This proxy, called Runtime Called Wrapper (or RCW), is an object that sits between COM and .NET, and translates calls from .NET to COM. To the .NET client, the proxy looks like any other .NET component, and the proxy takes care of interpreting the calls to COM. Creating the RCW is not a daunting task, as you will see in a minute.

You first create a COM component in VFP. The following code creates a sort of business object class that.NET will use. (We say sort of business object because the data access code is there too, but separating layers is not the point we're trying to make here):

Define Class CustomerBizObj As Session OlePublic DataSession = 2 && Private Session Procedure Init Use Home(2) + "\Northwind\Customers.dbf" EndProc Procedure GetCustomerList() As String Local lcOut As String lcOut = "" Cursortoxml("Customers","lcOut",1,0,0,"1") Return lcOut EndProc EndDefine


The GetCustomerList method retrieves a list of customers, returning the results in an XML string. Note that you must declare the return type, otherwise VFP will define the return type to be of type variant in the type library (a file that defines the methods and other things that are in a COM component). You need to avoid variants because .NET doesn't support a variant type. On the .NET side, the developer must know in advance what data type is actually getting returned to be able to use it.

You declare the class using the OlePublic keyword, marking it to be exposed as a COM component. For this demo we created a project called "COMInteropSample," and added the file CustomerBizObj.prg to the project. We need to build the project as a multi-threaded COM server (.dll).

You can use the following code to test the COM component in VFP:

*-- Instantiate the object. oCustomerBizObj=; CreateObject("COMInteropSample.CustomerBizObj") *-- Call the method, saving the XML to a file. StrToFile(oCustomerBizObj.GetCustomerList(),; "c:\CustomerList.xml") *-- Release the object. Release oCustomerBizObj *-- Show XML. Modify File c:\CustomerList.xml


Next you can create any sort of .NET application. For this example we've created an ASP.NET Web Application, and we chose to use C#, but the language really doesn't matter. After we created the project we added a reference to the COM component in the .NET project. You can do this by going to the Add Reference option on the Project menu, or by right-clicking the References node on the project through the Solution Explorer window (Figure 1 shows that). From the dialog box, click the Browse button, and navigate to the COMInteropSample.dll that was created when the VFP project was compiled.

 
Figure 1: Adding a reference to a .NET project.
Next we created a CustomerList.aspx Web Form, and added a DataGrid control (named dgCustomers) to it.

The CustomerBizObj class created in VFP will be contained within a namespace called cominteropsample, so we added the line using cominteropsample; at the top of the code-behind file for the Web Form. Inside that namespace you'll find the class named CustomerBizObjClass. This Web Form displays the list of Customer objects returned by the GetCustomerList method on the business object. The following code snippet shows the Page_Load method on the Web Form, which runs every time the page loads:



private void Page_Load(object sender, System.EventArgs e) { CustomerBizObjClass customer = new CustomerBizObjClass(); DataSet dsCustomers = new DataSet(); dsCustomers.ReadXml( new StringReader( customer.GetCustomerList())); this.dgCustomerList.DataSource = dsCustomers; this.dgCustomerList.DataBind(); }


As you can see, the code just instantiates the CustomerBizObjClass and a DataSet, which it fills with data based on the XML returned from GetCustomerList. The DataSet's ReadXml() method takes care of the transformation from XML to ADO.NET data. Finally, the code binds the DataSet to the DataGrid. Other than the specifics of using DataSets and StringReaders, using the VFP component is just a matter of instantiating objects and calling methods, as the VFP developer is very used doing in VFP. Figure 2 shows the results of running that page.

 
Figure 2: A .NET Web application that uses VFP components and data.
Remember what seemed to be a daunting task of creating the RCW (that proxy that intermediates .NET calls to COM components)? That's been created automatically by the Visual Studio .NET IDE as soon as a reference to the COM component was added to the .NET project. If you select the cominteropsample reference on the Solution Explorer window and look at its Path property, you should see something like the following:

C:\YourProject\obj\Interop.cominteropsample.dll


The YourProject portion of the path shown above should be whatever path you used for the .NET project you've created. The important detail to notice here is that the path doesn't point directly to the cominteropsample.dll (created by VFP). Instead, it points to an Interop.cominteropsample.dll. This DLL is the RCW created by .NET. This proxy will help .NET communicate with the COM component. It has a class with the same name as the one exposed by the COM component, but with the class word added to it (thus, the CustomerBizObjClass that's instantiated in the .NET sample). In other words, whenever your application instantiates that class in .NET, the proxy will know how to instantiate the COM component, and whenever a method is called in that class, the proxy will know how to translate the .NET call into a COM call.

The Type Library Importer Tool
When you add a reference to a COM component to a .NET project using the VS.NET IDE, VS uses a tool called the Type Library Importer, accepting default values for it. Some of those defaults determine that the proxy will be named after the COM DLL, but preceded by the word "interop" (such as in Interop.cominteropsample.dll), and the proxy class will be placed inside a namespace also named after the .dll (such as cominteropsample).

Many developers want to have more control over the process of creating the RCW, particularly the namespace where the proxy is going to be placed, and where the proxy DLL is going to be created. Developers can use the Type Library Importer tool (Tlbimp.exe) for that. This command-line tool installs with the .NET SDK in the folder C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin\. You can run the tool at a DOS prompt like this: (We broke the lines for better readability, but this would all be typed on one line.)

tlbimp.exe "C:\YourVFPProject\BizObjects.dll" /out: "C:\YourDotNetProject\bin\Proxy.BizObjects.dll" /namespace:BizObjects


Notice that you specify the COM DLL, and then use the switch out to specify where you want to locate the proxy and what you want to name it. Use the namespace switch to specify the name of the namespace that will contain the proxy class.

At this point you can remove the reference created previously in the .NET project for the COM component. You can add a new reference pointing to the Proxy.BizObjects.dll you just created via the command line. (The RCW is already a .NET class so VS.NET won't try to create another proxy). You can rewrite the using statement at the top of the Web Form as using BizObjects.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap