Class wwDotnetBridge

Shortcuts:

wwDotnetBridge allows you to access the vast majority of .NET components directly from FoxPro. It provides registrationless activation of .NET Components, and acts as a proxy into .NET that makes it possible to access features that native COM Interop does not support directly.

To work around COM limitations, wwDotnetBridge provides many improvements and work arounds, while still using the base layer of COM Interop for the inter-process communication. Everything that works with native COM Interop also works with wwDotnetBridge - it's the same technology after all - but you get many more support features and automatic type translations to work around the limitations.

The key features of wwDotnetBridge are:

  • Registrationless access to most .NET Components
    Unlike native COM Interop, you can instantiate and access .NET Components and static classes, without requiring those classes to be registered as COM objects. Objects are instantiated from within .NET, so you can access most .NET components by directly loading them from their DLL assembly. Both .NET Framework (wwDotnetBridge) and .NET Core (wwDotnetCoreBridge) are supported.

  • Instantiates and Interacts with .NET Objects via COM from within .NET
    wwDotnetBridge is a .NET based component that runs inside of .NET and acts as a proxy for activation, invocation and access operations. It creates any .NET instances from within .NET and returns those references using COM Interop. Once loaded you can use all features that COM supports directly: Property access and method calls etc. as long the members accessed use types that are supported by COM.

  • Support for Advanced .NET Features that COM Interop doesn't support
    Unfortunately there are many .NET features that COM and FoxPro don't natively support directly: Anything related to .NET Generics, overloaded methods, value types, enums, various number types to name just a few. But because wwDotnetBridge runs inside of .NET, it can proxy invocations via Reflection and access most features regardless of whether they are supported over COM or FoxPro. The core helper methods are InvokeMethod(), GetProperty() and SetProperty() as well as their static counterparts.

  • Automatic Type Conversions and Type Helpers
    Because there are many incompatible types in .NET that don't have equivalents in COM or FoxPro, wwDotnetBridge performs many automatic type conversions when using the above proxy methods. This make it easier to call methods or retrieve values from .NET by automatically converting to FoxPro compatible types. For example: decimals to double, long, byte to int, Guid to string etc. Some types can't be passed into FoxPro at all, so there are also wrapper classes like ComArray that wraps .NET Arrays and Collections and provides a FoxPro friendly interface for navigating and updating collections, and ComValue which wraps incompatible .NET values and provides convenience methods to set and retrieve the value in a FoxPro friendly way and pass it to .NET methods or property assignments.

  • Support for Async Code Execution
    A lot of modern .NET Code uses async functionality via Task based interfaces, and wwDotnetBridge includes a InvokeTaskMethodAsyc() helper that lets you call these async methods and receive results via Callbacks asynchronously. You can also run any .NET synchronous method and call it asynchronously using InvokeMethodAsync() using the same Callback mechanism.

Getting Started

The first step in using wwDotnetBridge is to load it for the first time, which instantiates the .NET Runtime. We recommend that you do this somewhere in your application startup sequence so as to avoid any potential version ambiguities. Somewhere in the startup of your application call InitializeDotnetVersion():

DO wwDotnetBridge               && Loads dependencies
InitializeDotnetVersion("V4")   && Loads .NET Runtime and caches it

Note that InitializeDotnetVersion() is optional. You can use GetwwDotnetBridge() or CREATEOBJECT("wwDotnetBridge"), but using InitializeDotnetVersion() ensures a reliable and predictable load of .NET on startup.

Unable to load CLR Instance Errors

If you get an Unable to CLR Instance error when creating an instance of wwDotnetBridge, you probably need to unblock the wwdotnetbridge.dll or need to ensure that the wwdotnetbridge.dll and wwipstuff.dll are in your FoxPro path. Please see Unable to load CLR Instance for more info.

Loading DLLs from Network Locations: Configuration required

.NET components require explicit configuration in order to support remote loading from network locations. This is done by creating a configuration file for your application yourapp.exe.config or the VFP IDE vfp9.exe.config, in their respective startup folders. We recommend at minimum you use the following .config file settings:

<?xml version="1.0"?>
<configuration>
  <runtime>
      <loadFromRemoteSources enabled="true"/>
  </runtime>
</configuration>

wwDotnetBridge Example

With the library loaded, you can retrieve an instance by calling the GetwwDotnetBridge() factory function which caches a loaded wwDotnetBridge instance and therefore is very fast to access.

Here's an example what of some of what you can then do:

*** Create or get cached instance of wwdotnetbridge
LOCAL loBridge as wwDotnetBridge
loBridge = GetwwDotnetBridge()

*** The first two are built-in .NET Framework functions so no assembly has to be loaded

*** Create a built-in .NET class and execute a method - this one downloads a file to disk
loHttp = loBridge.CreateInstance("System.Net.WebClient")
loHttp.DownloadFile("http://west-wind.com/files/MarkdownMonsterSetup.exe",
                    "MarkdownMonsterSetup.exe")

*** Format a string: Static method: Typename as string, method, parameters
? loBridge.InvokeStaticMethod("System.String","Format","Hello {0}. Time is: {1:t}",;
                              "Rick", DATETIME())
* Hello Rick. Time is: 2:45 PM                              

*** Now load a third party Assembly - assemblies load their own dependencies!
? loBridge.LoadAssembly("wwDotnetBridgeDemos.dll")

*** Create a class Instance - naming is: namespace.class
loPerson = loBridge.CreateInstance("wwDotnetBridgeDemos.Person")

*** Access simple Properties - plain COM
? loPerson.Name
? loPerson.Company
? loPerson.Entered

*** Call simple method - plain COM
? loPerson.ToString()
? loPerson.AddAddress("1 Main","Fairville","CA","12345")  && 2 Addresses now

*** Access an Array/Collection of Objects and iterate over the list
*** Arrays/Collections/Dictionaries are not easily accessible via COM
*** wwDotnetBridge returns a `ComArray` instance
loAddresses = loBridge.GetProperty(loPerson,"Addresses");

*** Access ComArray.Count list count
lnCount = loAddresses.Count   && 2 addresses

*** Access the first item - 0 based list
loAddress = loAddress.Item(0);
? loAddress.Street
? loAddress.ToString()

*** Add another item to the array
* loNewAddress = loBridge.CreateInstance("wwDotnetBridgeDemos.Address")
loNewAddress = loAddresses.CreateItem()
loNewAddress.Street = "122 Newfound Landing"
loNewAddress.City = "NewFoundLanding"
loAddresses.Add(loNewAddress)

? TRANSFORM(loAddresses.Count) + " Addresses"  && 3

*** Iterate through the entire list (3 items now): Remember 0 based!
FOR lnX = 0 to loAddresses.Count -1 
    loAddress = loAddresses.Item(lnX)
    ? loAddress.ToString()
    ? 
ENDFOR

All interactions occur over COM so any object instances are COM objects with typical .NET COM behavior (no Intellisense, COM style errors). Any properties and methods that use standard types can be directly accessed via their normal COM property and method names. Any members or methods that use types that are incompatible with COM (Value types, Generics, Long, Decimal, Guid etc.) have to use the indirect access methods GetProperty(), SetProperty() or InvokeMethod() for access.

If direct access fails for whatever reason, always try the indirect methods.

For much more detailed wwDotnetBridge and .NET Interop information you can also check out the white paper:

Custom
  wwDotnetBridge

Class Members

MemberDescription

ConvertToDotNetValue

Converts a FoxPro value of an 'unsupported' type to a .NET type by either using a FoxPro CAST() or converting the object into a wwDotnetBridge .NET ComValue object.

o.ConvertToDotNetValue(lvValue, lcType)

CreateArray

Creates a new ComArray instance based on the .NET type you specify as a parameter.

o.CreateArray(lvArrayInstanceOrTypeName)

CreateComValue

Creates an instance of a ComValue object which allows you to capture values from method calls and properties and keep them in .NET.

o.CreateComValue(lvValue)

CreateInstance

Creates an instance of a .NET class and passes it back to Visual FoxPro as a COM reference.

o.CreateInstance(lcClass, lvParm1, lvParm2, lvParm3, lvParm4, lvParm5)

CreateInstanceOnType

Allows creation of a new .NET type and assigning that type to a .NET object property without ever going through Visual FoxPro. This allows for creation on non-COM visible types in .NET and indirect manipulation of them.

o.CreateInstanceOnType(loInstance,lcProperty, lcClass,lvParm1,lvParm2, lvParm3, lvParm4, lvParm5)

DisposeInstance

Disposes a .NET object instance. Only works with objects that support IDisposable.

o.DisposeInstance(loInstance)

GetDictionaryItem

Returns an item from an IDictionary collection by key.

o.wwDotNetBridge.GetDictionaryItem(loDictionary, lvKey)

GetEnumString

Retrieves the string enum field name from a .NET Enum value.

o.GetEnumString(lcEnumType, lvEnumValue)

GetEnumValue

Retrieves a .NET Enumerated value by passing in a string representation and retrieving the corresponding numeric value.

o.GetEnumValue(lcType, lcValue)

GetField

Retrieves the value of a public field.

o.GetField(loInstance, lcFieldname)

GetIndexedProperty

Returns an array value by its index.

o.GetIndexedProperty(loListInstance, lnIndex)

GetProperty

Retrieves a property value from an object instance via Reflection.

o.GetProperty(loInstance, lcProperty)

GetPropertyRaw

Works the same as GetProperty(). but while that method returns a fixed up FoxPro friendly value, this method tries to return the raw result value directly as a .NET type.

o.wwDotNetBridge.GetPropertyRaw(loInstance,lcProperty,llNoInstanceFixup)

GetStaticProperty

Retrieves a static property from a .NET type.

o.GetStaticProperty(lcType, lcProperty)

GetwwDotNetBridge

Factory method that can be used to create a PUBLIC instance of the wwDotNetBridge class. Use this method instead of explicitly instantiating the class to avoid recreating the .NET object wrapper object each time.

GetwwDotNetBridge(lcVersion)

GetwwDotNetCoreBridge

Factory method that can be used to create a PUBLIC instance of the wwDotNetBridge class. Use this method instead of explicitly instantiating the class to avoid recreating the .NET object wrapper object each time.

GetwwDotNetCoreBridge(lcVersion)

Init

Constructor for the wwDotNetBridge class. Allows specification of the .NET runtime to be used via optional parameter. Last optional parameter determines whether .NET runtime is loaded directly into VFP or whether the .NET component is loaded via COM Interop.

o.wwDotNetBridge.Init(lcDotNetVersion, llUseComInterop)

InitializeDotnetCoreVersion

Use this function in your application's startup program to force the 32 bit .NET Core Runtime version to be used by wwDotnetBridgeCore for the entire application. This loads the runtime and thus determines the runtime that will be used for the entire application making calls with wwDotnetBridgeCore.

InitializeDotnetCoreVersion(lcVersion)

InitializeDotnetVersion

Use this function in your application's startup program to force the .NET Runtime version to be used by wwDotnetBridge for the entire application. This loads the runtime and thus determines the runtime that will be used for the entire application making calls with wwDotnetBridge.

InitializeDotnetVersion(lcVersion)

InvokeMethod

Invokes a method on a .NET object instance.

o.InvokeMethod(loInstance,lcMethod,lvParm1,...lvParm10)

InvokeMethodAsync

This useful method allows you to turn any .NET Method you call into an asynchronously called method that returns a callback to you on completion rather than an immediate result.

o.InvokeMethodAsync(loCallbackEvents,     loInstance,     lcMethod,     lvParm1-10)

InvokeMethod_ParameterArray

Like InvokeMethod, but allows passing an arbitrary number of parameters in an array rather than as a named parameter. The array is translated into individual parameters passed into the method called.

o.InvokeMethod_ParameterArray(loInst,lcMethod,laParams)

InvokeStaticMethod

This method allows you to call a static .NET method such as System.Windows.Forms.MessageBox.Show() for example. Because the methods are static you can't create an instance and pass it back to FoxPro, instead this method has to be used to invoke a method by using a fully qualified type name instead of an instance.

o.InvokeStaticMethod(lcTypeName, lcMethod, lvParm1, ... lvParm10)

InvokeStaticMethodAsync

Invokes a .NET static method asynchronously on a seperate thread and fires OnCompleted() and OnError() events into the passed in Callback object.

o.InvokeStaticMethodAsync(loCallback,lcTypeName,lcMethod,lvParm1-10)

InvokeTaskMethodAsync

This method allows you to call any .NET async method - any method that returns a Task object basically - asynchronously by passing in a callback object that is called back when the async method completes or fails.

o.wwDotNetBridge.InvokeTaskMethodAsync(loCallback, loInstance, loMethod)

LoadAssembly

Loads a .NET assembly into the .NET Runtime currently executing. Note that you should ensure that any required assemblies and dependent assemblies are loaded explicitly into the runtime.

o.LoadAssembly(lcAssembly)

SetField

Sets the value of a public field.

o.SetField(loInstance, lcFieldName, lvValue)

SetProperty

Sets a .NET object property via Reflection.

o.SetProperty(loInstance,lcProperty,lvValue)

SetStaticProperty

Sets a static property or Enum value. Same behavior as SetProperty() but with static properties.

o.SetStaticProperty(lcType,lcProperty,lcValue)

SubscribeToEvents

Allows you to capture events on a source object, by passing in a callback handler that maps the events of the target object with corresponding methods on the handler.

o.SubscribeToEvents(loSource, loHandler, lcPrefix)

ToJson

Creates a JSON string from a .NET object or value passed in.

o.ToJson(loDotnetObject)

ToString

Returns the result from the .ToString() method reliably. ToString() often is overridden and so not directly accessible via direct COM access. This method internally calls InvokeMethod() on to call the .NET ToString().

o.ToString(loDotnetObject, lcFormat)

Unload

Unloads the .NET AppDomain and any loaded assemblies within it.

o.Unload()

cErrorMsg

Contains an error message if a method call fails.

lError

Error flag that can be checked after certain method calls.

oLastException

Returns the last .NET exception that was caused by a failed operation.

Requirements

Assembly: wwdotnetbridge.prg

See also:

wwDotNetBridge Examples | What is wwDotnetBridge? | wwDotnetBridge Features

© West Wind Technologies, 1996-2024 • Updated: 10/06/24
Comment or report problem with topic