Accessing IEnumerable Lists
In .NET many list results are returned as IEnumerable of one type or another and some of these types - especially results from LINQ Queries can be completely virtual: They are forward only, read data structures that are read one at a time as they are iterated over.
Unfortunately COM does not support virtual only data structures for by REF marshalling used for FoxPro COM calls. The work around is to create an array out of the IEnumerable and then use that in FoxPro.
The ComArray class includes a FromEnumerable method that can handle this for us. Here's an example that retrieves list of entries from a business object in .NET. The result is of IEnumerable and is the result of a dynamic LINQ query. The data is not live until iterated over.
The code to access the Entries looks like this:
loBridge = CreateObject("wwDotNetBridge","V4") loBridge.LoadAssembly("bin\TimetrakkerBusiness.dll") loEntry = loBridge.CreateInstance("TimeTrakker.busEntry") *** Result is an IEnumerable and FoxPro can't use it *loEntries = loEntry.GetEntries(1) loEntries = loBridge.Invokemethod(loEntry,"GetEntries",1) *** Create a ComArray instance and convert the *** IEnumerable to an array we can use in FoxPro loArray = loBridge.CreateArray() loArray.FromEnumerable(loEntries) ? loArray.Count *** Now we can iterate over the list FOR lnX = 0 TO loArray.Count -1 loEntry = loArray.Item(lnX) ? loEntry.Title + " - " + TRANSFORM(loEntry.Timein) ENDFOR
The key part of this code is the conversion from a dynamic IEnumerable to an array.
loArray = loBridge.CreateArray() loArray.FromEnumerable(loEntries)
This creates a new empty ComArray instance and then loads it with the IEnumerable result. The method converts the IEnumerable a .NET array and stores it on the Instance property of the ComArray. Once this is done the ComArray instance can be used like normal to iterate over the array items.
Note that if your list is very large, this can cause some severe memory usage. Typically dynamic IEnumerable usage is done to minimize memory consumption as only one item gets loaded into memory. When you use ComArray.FromEnumerable() you are in effect loading the entire list into memory.
There's not much of a choice but you need to be aware of this behavior and try to ensure you get a suitable subset of data returned to avoid overuse of memory as much as possible.
Comment or report problem with topic