Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

The dynamic Type in C# Simplifies COM Member Access from Visual FoxPro


:P
On this page:

I’ve written quite a bit about Visual FoxPro interoperating with .NET in the past both for ASP.NET interacting with Visual FoxPro COM objects as well as Visual FoxPro calling into .NET code via COM Interop. COM Interop with Visual FoxPro has a number of problems but one of them at least got a lot easier with the introduction of dynamic type support in .NET. One of the biggest problems with COM interop has been that it’s been really difficult to pass dynamic objects from FoxPro to .NET and get them properly typed. The only way that any strong typing can occur in .NET for FoxPro components is via COM type library exports of Visual FoxPro components. Due to limitations in Visual FoxPro’s type library support as well as the dynamic nature of the Visual FoxPro language where few things are or can be described in the form of a COM type library, a lot of useful interaction between FoxPro and .NET required the use of messy Reflection code in .NET.

Reflection is .NET’s base interface to runtime type discovery and dynamic execution of code without requiring strong typing. In FoxPro terms it’s similar to EVALUATE() functionality albeit with a much more complex API and corresponiding syntax. The Reflection APIs are fairly powerful, but they are rather awkward to use and require a lot of code. Even with the creation of wrapper utility classes for common EVAL() style Reflection functionality dynamically access COM objects passed to .NET often is pretty tedious and ugly.

Let’s look at a simple example. In the following code I use some FoxPro code to dynamically create an object in code and then pass this object to .NET. An alternative to this might also be to create a new object on the fly by using SCATTER NAME on a database record. How the object is created is inconsequential, other than the fact that it’s not defined as a COM object – it’s a pure FoxPro object that is passed to .NET. Here’s the code:

*** Create .NET COM Instance
loNet
= CREATEOBJECT('DotNetCom.DotNetComPublisher') *** Create a Customer Object Instance (factory method) loCustomer = GetCustomer() loCustomer.Name = "Rick Strahl" loCustomer.Company = "West Wind Technologies" loCustomer.creditLimit = 9999999999.99 loCustomer.Address.StreetAddress = "32 Kaiea Place" loCustomer.Address.Phone = "808 579-8342" loCustomer.Address.Email = "rickstrahl@hotmail.com" *** Pass Fox Object and echo back values ? loNet.PassRecordObject(loObject) RETURN FUNCTION GetCustomer LOCAL loCustomer, loAddress loCustomer = CREATEOBJECT("EMPTY") ADDPROPERTY(loCustomer,"Name","") ADDPROPERTY(loCustomer,"Company","") ADDPROPERTY(loCUstomer,"CreditLimit",0.00) ADDPROPERTY(loCustomer,"Entered",DATETIME()) loAddress = CREATEOBJECT("Empty") ADDPROPERTY(loAddress,"StreetAddress","") ADDPROPERTY(loAddress,"Phone","") ADDPROPERTY(loAddress,"Email","") ADDPROPERTY(loCustomer,"Address",loAddress) RETURN loCustomer ENDFUNC

Now prior to .NET 4.0 you’d have to access this object passed to .NET via Reflection and the method code to do this would looks something like this in the .NET component:

public string PassRecordObject(object FoxObject) 
{
    // *** using raw Reflection
    string Company = (string) FoxObject.GetType().InvokeMember(
        "Company",   
        BindingFlags.GetProperty,null, 
        FoxObject,null);

    // using the easier ComUtils wrappers
    string Name = (string) ComUtils.GetProperty(FoxObject,"Name");

    // Getting Address object – then getting child properties
object Address = ComUtils.GetProperty(FoxObject,"Address");
    string Street = (string) ComUtils.GetProperty(FoxObject,"StreetAddress");

    // using ComUtils 'Ex' functions you can use . Syntax 
    string StreetAddress = (string) ComUtils.GetPropertyEx(FoxObject,"AddressStreetAddress");

return Name + Environment.NewLine + Company + Environment.NewLine + StreetAddress + Environment.NewLine + " FOX"; }

Note that the FoxObject is passed in as type object which has no specific type. Since the object doesn’t exist in .NET as a type signature the object is passed without any specific type information as plain non-descript object. To retrieve a property the Reflection APIs like Type.InvokeMember or Type.GetProperty().GetValue() etc. need to be used. I made this code a little simpler by using the Reflection Wrappers I mentioned earlier but even with those ComUtils calls the code is pretty ugly requiring passing the objects for each call and casting each element.

Using .NET 4.0 Dynamic Typing makes this Code a lot cleaner

Enter .NET 4.0 and the dynamic type. Replacing the input parameter to the .NET method from type object to dynamic makes the code to access the FoxPro component inside of .NET much more natural:

public string PassRecordObjectDynamic(dynamic FoxObject)
{
    // *** using raw Reflection
    string Company = FoxObject.Company; 

    // *** using the easier ComUtils class
    string Name = FoxObject.Name;

    // *** using ComUtils 'ex' functions to use . Syntax
    string Address = FoxObject.Address.StreetAddress;

    return Name + Environment.NewLine +
        Company + Environment.NewLine +
        Address + Environment.NewLine + " FOX";
}

As you can see the parameter is of type dynamic which as the name implies performs Reflection lookups and evaluation on the fly so all the Reflection code in the last example goes away. The code can use regular object ‘.’ syntax to reference each of the members of the object. You can access properties and call methods this way using natural object language. Also note that all the type casts that were required in the Reflection code go away – dynamic types like var can infer the type to cast to based on the target assignment. As long as the type can be inferred by the compiler at compile time (ie. the left side of the expression is strongly typed) no explicit casts are required.

Note that although you get to use plain object syntax in the code above you don’t get Intellisense in Visual Studio because the type is dynamic and thus has no hard type definition in .NET .

The above example calls a .NET Component from VFP, but it also works the other way around. Another frequent scenario is an .NET code calling into a FoxPro COM object that returns a dynamic result.

Assume you have a FoxPro COM object returns a FoxPro Cursor Record as an object:

DEFINE CLASS FoxData AS SESSION OlePublic

cAppStartPath = ""

FUNCTION INIT
THIS.cAppStartPath = ADDBS( JustPath(Application.ServerName) )
SET PATH TO ( THIS.cAppStartpath )
ENDFUNC


FUNCTION GetRecord(lnPk)
LOCAL loCustomer

SELECT * FROM tt_Cust WHERE pk = lnPk ;
         INTO CURSOR TCustomer
         
IF _TALLY < 1
   RETURN NULL
ENDIF    

SCATTER NAME loCustomer MEMO
RETURN loCustomer
ENDFUNC

ENDDEFINE

If you call this from a .NET application you can now retrieve this data via COM Interop and cast the result as dynamic to simplify the data access of the dynamic FoxPro type that was created on the fly:

int pk = 0;
int.TryParse(Request.QueryString["id"],out pk);

// Create Fox COM Object with Com Callable Wrapper
FoxData foxData = new FoxData();

dynamic foxRecord = foxData.GetRecord(pk);

string company = foxRecord.Company;
DateTime entered = foxRecord.Entered;

This code looks simple and natural as it should be – heck you could write code like this in days long gone by in scripting languages like ASP classic for example. Compared to the Reflection code that previously was necessary to run similar code this is much easier to write, understand and maintain.

For COM interop and Visual FoxPro operation dynamic type support in .NET 4.0 is a huge improvement and certainly makes it much easier to deal with FoxPro code that calls into .NET. Regardless of whether you’re using COM for calling Visual FoxPro objects from .NET (ASP.NET calling a COM component and getting a dynamic result returned) or whether FoxPro code is calling into a .NET COM component from a FoxPro desktop application. At one point or another FoxPro likely ends up passing complex dynamic data to .NET and for this the dynamic typing makes coding much cleaner and more readable without having to create custom Reflection wrappers. As a bonus the dynamic runtime that underlies the dynamic type is fairly efficient in terms of making Reflection calls especially if members are repeatedly accessed.

Posted in COM  FoxPro  .NET  CSharp  

The Voices of Reason


 

Jonathan Allen
September 13, 2010

# re: The dynamic Type in C# Simplifies COM Calls from Visual FoxPro

I wish you wouldn't say "COM objects passed to .NET often is pretty tedious and ugly." VB.NET has been handling COM objects just fine since .NET 1.0. JScript.NET, IronPython, and IronRuby likewise never had any problems. It is only C# that has been screwing this up.

Brought to you by the Committee to Demonstrate that VB.NET Kicks Ass

Rick Strahl
September 14, 2010

# re: The dynamic Type in C# Simplifies COM Calls from Visual FoxPro

@Jonathan - VB.NET only made COM Interop easy (prior to .NET 4.0) if option strict is off which is hardly a best practice... Anyway, the point is that it is no longer a problem as you get the native functionality in the runtime now without having to make everything weakly typed. C# 4.0's dynamic typing uses the same dynamic runtime that IronPython and IronRuby use for their main type system to support dynamic typing.

Serge
October 12, 2011

# re: The dynamic Type in C# Simplifies COM Member Access from Visual FoxPro

I'm trying to get all properties of a Foxpro COM object in C# 4.0, but when I call GetProperties() (even with BindingTags) I always get an empty array.
It's like C# is preventing me from retrieving the properties that way (though you can still use obj.property = value).

typeof(DigimediaWS.CUST).GetProperties() => System.Reflection.PropertyInfo[0]

Do you have any idea how to work arround that

Rick Strahl
October 12, 2011

# re: The dynamic Type in C# Simplifies COM Member Access from Visual FoxPro

@Serge - COM Types that are dynamic or of type object can't be reflected because they are merely proxies not a .NET object.

You can invoke members (call methods, get/set properties) by using Type.InvokeMember() which is the only thing I've found to work to make COM 'reflection' work. But you can't iterate over COM objects using Reflection directly (unless you import them into .NET with an Interop assembly in which case they become .NET types that wrap the COM proxy).

Sanchi
December 23, 2011

# re: The dynamic Type in C# Simplifies COM Member Access from Visual FoxPro

Can i get the Type of the member property of the Foxobject sent to C#? or how do i get the type of fields or dynamic properties created using "Scatter name loCustomer Memo"? Do i have to predefine the typed variable for taking the values?

Rick Strahl
December 23, 2011

# re: The dynamic Type in C# Simplifies COM Member Access from Visual FoxPro

@Sanchi - FoxPro types will never show up as a 'strong' type in .NET only as type object. The only way to get a strong .NET type is if the type somehow originated in .NET in the first place - ie. as a .NET type passed over COM Interop for example.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024