So you're doing a bunch of COM Interop with .NET. Whether you're using plain COM Interop or the richer functionality offered by wwDotnetBridge, you probably already know that finding the approriate .NET type names is tedious. FoxPro code in either case must reference the full .NET typename which includes the namespace and class name.
For example check out this code that loops through personal certificate store on the local machine using wwDotnetBridge. I've highlighted all the .NET type names used in this small snippet in bold:
do wwDotNetBridge LOCAL loBridge as wwDotNetBridge loBridge = CreateObject("wwDotNetBridge","V4") *** Create an instance of 509Store loStore = loBridge.CreateInstance("System.Security.Cryptography.X509Certificates.X509Store") *** Grab a static Enum value leReadOnly = loBridge.GetEnumvalue("System.Security.Cryptography.X509Certificates.OpenFlags","ReadOnly") *** Open the certificate store - results into loStore.Certificates loStore.Open(leReadOnly) *** Collection of Certificates laCertificates = loStore.Certificates *** Collections don't work over regular COM Interop *** so use indirect access lnCount = loBridge.GetProperty(laCertificates,"Count") *** Loop through Certificates FOR lnX = 1 TO lnCount -1 *** Access collection item indirectly LOCAL loCertificate as System.Security.Cryptography.X509Certificates.X509Certificate2 loCertificate = loBridge.GetPropertyEx(loStore,"Certificates[" + TRANSFORM(lnX) + "]") IF !ISNULL(loCertificate) ? loCertificate.FriendlyName ? loCertificate.SerialNumber ? loBridge.GetPropertyEx(loCertificate,"IssuerName.Name") ENDIF ENDFOR RETURN
How the heck do you figure out all those type names used in this code?
Answer: You use a .NET disassembling tool that provides insight into a .NET assembly. Regardless of whether you're using a system component or custom .NET component of your own being able to look up exact type names is critical if you do .NET COM Interop.
My favorite tool to do this is Red Gate's .NET Reflector. .NET Reflector is free up to version 6.8 and a relatively cheap tool for all that it provides from version 7.0 forward. All the features described here work in 6.x although I'm using version 7.
Using Reflector basically allows you to point at any DLL on disk and show all the contained types and resources that are available. It can also load assemblies from the GAC and by default it loads up a number of common .NET runtime components.
Here's a view of Reflector with the X509Store class open and selected:
Reflector provides a number of important pieces of information for Interop. It basically lets you browser the .NET component that you might want to access and call methods or access properties on. You can at a glance see what the component does and how you need to interact with it.
The next important thing is that you can get the full class name for any type. Notice in the bottom left window it gives the name of the type, its definition and the fully qualified type name that includes the full namespace and class. THIS is the type name you generally need for the wwDotnetBridge CreateInstance call.
loStore = loBridge.CreateInstance("System.Security.Cryptography.X509Certificates.X509Store")
I can't stress how important this particular piece of information is because while you might know what the name of a particular .NET class is often it's not so easy to figure out what the full name is. This is especially true if you're loading a third party assembly that might not be well documented. .NET components frequently omit detailed full type information documentation because .NET developers are used to Intellisense and Visual Studio helping them inject assembly and namespace references into their code. As FoxPro developers doing interop we don't have that luxury so for us using a tool like Reflector is vitally important.
Next you can also get detailed information about the methods that you call in .NET. Again this is vitally important as you have to ensure that you are passing the right parameters to .NET and that these types match the .NET signature. Type marshalling from FoxPro -> .NET doesn't always work as expected especially when dealing with numeric values (don't forget to use CAST()).
For the method view we get the full parameter signature plus a disassembled view of the actual code:
The disassembled code is very useful for .NET developers at times. As Fox developers all we care about is the method signature though. We can see all the parameters that are passed and all complex types (like the OpenFlags Enum here) are linked, so you can click on the link and directly navigate to the Enum type:
Now what's cool here is that you get to see the actual typename as before and we can now use wwDotnetBridge's Enum functionality to create the enum value in FoxPro code:
leReadOnly = loBridge.GetEnumvalue("System.Security.Cryptography.X509Certificates.OpenFlags","ReadOnly") loStore.Open(leReadOnly)You can see that I need the full type name here, and I can get that from the Name property in the window on the lower left.
However, there's actually an easier way: Since Reflector shows me the disassembled code it also shows me the Flag values for this particular enumeration. I can actually bypass the enumeration and just use the numeric value:
loStore.Open(0) && leReadOnly)
and it works just the same. Note that this will work as long the Enum is actually a flag value - not all enumerated values in .NET translate to a flag value so not all enums translated into numbers. You'll know because Reflector won't show the numbers if that's the case.
What's that Assembly Name from the GAC?
To find this assembly in Reflector from the GAC I can use File | Open Global Assembly Cache and then look at the assembly in the list view:
And now the strong assembly name shows up in the name property on the bottom which I can then use in my LoadAssembly call:
loBridge.LoadAssembly("System.Web.Extensions, Version=220.127.116.11, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
Note with GAC components - especially those from Microsoft - the hardest part often is to figure which assembly components live in. When in doubt punch in a search into your favorite search engine and look at MSDN entries. As ineffectual as MSDN documentation often is, it does provide you with the necessary type information most of the time:
You get the two important pieces of information you need: The assembly the component lives in and the full namespace. Once you load the assembly you can easily look up the namespace and find the class in Reflector.
Reflector in the real World
I have a tool called West Wind Web Service Proxy Generator, which is a tool that creates Web Service clients from a WSDL document for Visual FoxPro applications. This tool works by looking at a WSDL document and create a .NET proxy class, and a FoxPro class that calls this .NET proxy class. In the process we end up with a 1-1 mapping of Web Service methods to FoxPro class methods.
Web Services can get very complex and most of the time these Web Services include a slew of support types that make up the various message objects that are used to pass parameters to and from the Web Service. For example, if you look at the Amazon SOAP Web Services you'll find that there are hundreds of support objects! But even simpler services end up at least with a handful of objects. Since .NET imports the WSDL from the Web and dynamically generates these types as part of the import there is no explicit documentation for them. A tool like Reflector is a life saver to figure out what the service makes available.
Here's an example:
In this case there's one service class (at the bottom) and about a dozen message classes that are used as part of the requests. Figuring out the full type names for each of these types is not exactly obvious and finding out each of the object's properties isn't either. It's tremendously helpful to be able to look at Reflector and to look at the method I'm calling, following it to the message type that needs to be sent to get the object name and then be able to access each of the properties of each of these objects.
Reflect on this!
Ok, so Reflector is very cool, but Reflector has kind of a checkered history and it's not the only game in town anymore. Reflector started out as an open source tool by Lutz Roeder who maintained it until version 4.0. Red Gate took over the product and although they promised to keep it free eventually started forcing people to upgrade to Version 7.0 with a nasty forced upgrade. I've been bitten by this as I've been linking Reflector as part of the West Wind Web Service Proxy Generator, so lots of people actually used Reflector in conjunction with this tool. When Reflector 7 came out Red Gate tried to force people to upgrade and when they didn't they actually removed the running copy of Reflector - it self-destructed and broke some of the links in my tool. Argh! I was pissed.
Red Gate recently reversed that last bit and now Version 6.8 can be used for free (if you can find a copy of V6) and it won't ask to upgrade or self destruct, but the catch is that you have to have an existing copy of Reflector 6 to upgrade first (Red Gate took down Reflector 6 from their servers).
All that said I think that Reflector is a worthwhile tool to spend $35 on even if all you do is COM Interop. The latest version has a number of improvements you know you're running a tool that is kept up to date with the latest features and versions of the .NET runtime.
You can grab an eval copy of Reflector from here:
For what it's worth I use Reflector 7 and have upgraded because it's worth it and I have dependencies on it. I don't regret that, but I am pretty miffed at the way Red Gate handled this whole upgrade process.
Because of the way that Red Gate blundered their marketing on the move to version 7.0 a lot of people were pissed off and a number of alternatives have sprung up, all of them free. Most of these provide similar functionality as Reflector does although the user interface might be slightly different (out of these JustDecompile is probably closest to Reflector).
Open source tool that provides all the basic functionality of Reflector, but the UI is a bit more low level. Little harder to find things.
(requires .NET 4.0)
Telerik basically created a .NET Reflector clone using WPF. It's a nice and smooth application that provides the base features that .NET Reflector provides in a user interface that's very similar to Reflectors.
(requires .NET 4.0)
JetBrains also has a tool that competes in this space. It's more techy and provides many additional .NET features that won't be so useful to Interop developers. But as the others it provides the necessary tools to figure out type names and method signatures reliably.
(requires .NET 4.0)
As you can see all the alternate tools require .NET 4.0 while Reflector 6 and 7 still run on Version 2.0 which is nice as .NET 2.0 is widely pre-loaded while 4.0 is still trying to reach critical mass. Otherwise each of these tools should do the trick of helping you in your development.