Ejemplos
20 ejemplos progresivos que te llevan desde lo más básico de .NET hasta casos de uso reales: colecciones genéricas, async/await, HttpClient y más. Cada ejemplo es autocontenido y listo para pegar en tu proyecto.
loBridge = NEWOBJECT("FoxBridge", "FoxBridge.prg")
IF !loBridge.Activate(lcJwt)
? loBridge.GetLastError()
RETURN
ENDIFNivel básico: los primeros pasos
Ejemplo 1: StringBuilder, tu primer objeto .NET
StringBuilder es el mejor punto de partida: es simple, predecible y demuestra el ciclo completo de Create → llamar métodos → obtener resultado.
loBuilder = loBridge.Create("System.Text.StringBuilder", "Hola ")
loBuilder.Append("mundo ")
loBuilder.Append("desde FoxBridge!")
? loBuilder.ToString() && "Hola mundo desde FoxBridge!"
? loBuilder.Length && 27
loBuilder = .NULL.Ejemplo 2: Uri, inspeccionar una URL
System.Uri descompone una URL en sus partes (host, puerto, ruta, query). Demuestra el uso de Qualified Assembly Names (AQN) con la coma.
loUri = loBridge.Create("System.Uri, System", "https://api.miempresa.com:8080/v1/clientes?estado=activo")
? "Host: ", loUri.Host && "api.miempresa.com"
? "Puerto:", loUri.Port && 8080
? "Ruta: ", loUri.AbsolutePath && "/v1/clientes"
? "Query: ", loUri.Query && "?estado=activo"
loUri = .NULL.Ejemplo 3: LoadAssembly, usar tu propia DLL
El verdadero poder de FoxBridge: cargar una DLL que tu mismo compilaste en C# o VB.NET y llamar sus clases como si fueran objetos VFP nativos.
llOk = loBridge.LoadAssembly("C:\MiApp\bin\MiLogica.dll")
IF llOk
loFactura = loBridge.Create("MiLogica.Facturacion", 0.16) && IVA 16%
lnTotal = loFactura.CalcularTotal(1000.00)
? "Total con IVA:", lnTotal && 1160.00
loFactura = .NULL.
ENDIFNivel intermedio: colecciones, estáticos y excepciones
Ejemplo 4: List<String>, listas genéricas
FoxBridge convierte automáticamente List<T> en un proxy con los métodos Add, Remove, Item y Count. La indexación es base-1, como en VFP.
loLista = loBridge.Create("List<String>")
loLista.Add("Visual FoxPro")
loLista.Add("C#")
loLista.Add("F#")
loLista.Add("Go")
? "Total:", loLista.Count() && 4
? "Tercero:", loLista.Item(3) && "F#"
* Recorrer
For i = 1 to loLista.Count()
? Transform(i) + ". " + loLista.Item(i)
Next
loLista.Remove("Go")
? "Despues de Remove:", loLista.Count() && 3
loLista = .NULL.Ejemplo 5: DirectoryInfo, listar archivos
GetFiles() devuelve un array de objetos FileInfo. Cada elemento es un proxy FoxBridge con sus propias propiedades. Usamos GetObject(i) para acceder a cada elemento.
loDir = loBridge.Create("System.IO.DirectoryInfo", "C:\Windows")
loFiles = loDir.GetFiles()
? "Archivos encontrados:", loFiles.Count()
For i = 1 to Min(5, loFiles.Count())
loFile = loFiles.GetObject(i)
? "Nombre: " + loFile.Name
? "Tamano: " + Transform(loFile.Length) + " bytes"
? "Extension: " + loFile.Extension
loFile = .NULL.
Next
loFiles = .NULL.
loDir = .NULL.Ejemplo 6: Dictionary<String, String>, clave-valor
Los diccionarios de .NET en FoxBridge usan Set, Get, ContainsKey y Remove. Ojo con el nombre: es ContainsKey, no Contains. Cuando el valor es un objeto complejo, usa GetObject() en lugar de Get().
loDict = loBridge.Create("Dictionary<String, String>")
loDict.Set("nombre", "Irwin Rodriguez")
loDict.Set("pais", "Mexico")
loDict.Set("lang", "Visual FoxPro")
? "Contiene 'nombre':", loDict.ContainsKey("nombre") && .T.
? "Valor:", loDict.Get("nombre") && "Irwin Rodriguez"
loDict.Remove("lang")
? "Contiene 'lang' tras Remove:", loDict.ContainsKey("lang") && .F.
loDict = .NULL.Ejemplo 7: Resolución de sobrecargas, el Binder en acción
VFP solo tiene un tipo numerico (Double). FoxBridge detecta automáticamente el overload correcto para cada llamada. Aquí lo ponemos a prueba con Append(), que tiene 18 sobrecargas en .NET.
loSB = loBridge.Create("System.Text.StringBuilder")
loSB.Append("Entero: ")
loSB.Append(100) && VFP manda Double y el Binder busca la firma
&& exacta: resuelve a Append(double)
loSB.Append(" | Booleano: ")
loSB.Append(.T.) && VFP envia Logical, .NET resuelve a Append(bool)
loSB.Append(" | Double: ")
loSB.Append(45.67) && .NET resuelve a Append(double)
? loSB.ToString() && "Entero: 100 | Booleano: True | Double: 45.67"
loSB = .NULL.Ejemplo 8: Captura de excepciones .NET
Cuando un método .NET lanza una excepción, FoxBridge la convierte en un error VFP que puedes capturar con TRY/CATCH. El mensaje incluye la excepción original y la InnerException.
TRY
* Un URI invalido lanza FormatException en .NET
loUri = loBridge.Create("System.Uri, System", "esto no es una URL")
? "ERROR: no deberia llegar aqui"
CATCH TO loEx
? "Excepcion capturada:"
? loEx.Message && describe el error de .NET
ENDTRYEjemplo 9: Miembros estaticos, File, Guid, Environment
Clases como System.IO.File, System.Guid y System.Environment son completamente estaticas. loBridge.Static() devuelve un proxy que expone todos sus métodos y propiedades.
* Escribir y leer un archivo
loFile = loBridge.Static("System.IO.File")
loFile.WriteAllText("C:\foxbridge_test.txt", "Prueba de escritura estatica")
? loFile.Exists("C:\foxbridge_test.txt") && .T.
? loFile.ReadAllText("C:\foxbridge_test.txt")
loFile.Delete("C:\foxbridge_test.txt")
* Generar un GUID unico
loGuid = loBridge.Static("System.Guid")
loNewGuid = loGuid.NewGuid()
? "GUID nuevo:", loNewGuid.ToString() && "a1b2c3d4-..."
* Informacion del sistema
loEnv = loBridge.Static("System.Environment")
? "Maquina: ", loEnv.MachineName
? "Version OS: ", loEnv.OSVersion.ToString()
? "Procesadores:", loEnv.ProcessorCount
loFile = .NULL.
loGuid = .NULL.
loEnv = .NULL.Ejemplo 10: Propiedades estaticas de lectura/escritura
Algunas propiedades estaticas son de lectura/escritura (get+set). FoxBridge las trata como propiedades normales del proxy.
loEnv = loBridge.Static("System.Environment")
lcDirActual = loEnv.CurrentDirectory
? "Directorio actual:", lcDirActual
* Cambiar el directorio de trabajo
loEnv.CurrentDirectory = "C:\"
? "Nuevo directorio:", loEnv.CurrentDirectory && "C:\"
* Restaurar
loEnv.CurrentDirectory = lcDirActual
loEnv = .NULL.Nivel avanzado: rendimiento, binarios y async
Ejemplo 11: Enums como números, File.Open con FileMode y FileAccess
VFP no tiene enums, pero .NET los usa constantemente. FoxBridge acepta el valor entero del enum directamente. Consulta la documentación de MSDN para ver los valores numericos.
* FileMode.Open = 3, FileAccess.Read = 1
lcPath = "C:\foxbridge_enum_test.txt"
SET SAFETY OFF
StrToFile("datos de prueba", lcPath)
loFile = loBridge.Static("System.IO.File")
TRY
loStream = loFile.Open(lcPath, 3, 1) && Open para lectura
IF !IsNull(loStream)
? "Stream abierto. Longitud:", loStream.Length
loStream.Close()
loStream = .NULL.
ENDIF
CATCH TO loEx
? "Error:", loEx.Message
ENDTRY
IF File(lcPath)
Erase (lcPath)
ENDIF
loFile = .NULL.Ejemplo 12: Stress de rendimiento, 1000 llamadas a System.Math
FoxBridge cachea la resolución de métodos tras la primera llamada. Las siguientes invocaciones al mismo método son significativamente más rapidas.
loMath = loBridge.Static("System.Math")
lnStart = Seconds()
For i = 1 to 1000
lnVal = loMath.Max(i, 500)
lnVal = loMath.Sqrt(lnVal)
lnVal = loMath.Round(lnVal, 2)
Next
? "1000 llamadas en:", Seconds() - lnStart, "segundos"
? "Ultimo valor:", lnVal
loMath = .NULL.Ejemplo 13: Cadenas de propiedades anidadas
Cuando una propiedad devuelve otro objeto, FoxBridge lo envuelve automáticamente en un nuevo proxy. Puedes encadenar accesos con punto normalmente.
TRY
loProcess = loBridge.Static("System.Diagnostics.Process, System")
loProc = loProcess.GetCurrentProcess()
? "Proceso:", loProc.ProcessName
loModule = loProc.MainModule
? "Modulo: ", loModule.ModuleName
? "Ruta: ", loModule.FileName
loModule = .NULL.
loProc = .NULL.
CATCH TO loEx
? "Error:", loEx.Message
ENDTRYEjemplo 14: Manejo de valores nulos
FoxBridge traduce .NULL. de VFP a null de .NET cuando el método lo acepta. Cuando el método espera un tipo por valor (int, bool), lanzara excepción, que puedes capturar normalmente.
loSB = loBridge.Create("System.Text.StringBuilder")
* .NULL. a un parametro de tipo referencia: aceptado.
*
* Ojo con el caso de Append: tiene varias sobrecargas de referencia
* (string, object, char[], StringBuilder...), y el Binder resuelve por
* coincidencia exacta, sin heuristicas, asi que un null a secas puede
* quedar ambiguo. Cuando quieras un null de un tipo concreto, pasalo
* por una variable del tipo que sea, o usa un metodo de una sola
* sobrecarga.
TRY
loLista = loBridge.Create("List<String>")
loLista.Add(.NULL.)
? "OK: la lista acepta null como elemento"
CATCH TO loEx
? "Error:", loEx.Message
ENDTRY
* .NULL. a un parametro int: error controlado
TRY
loSB.EnsureCapacity(.NULL.)
CATCH TO loEx
? "Error esperado (int no acepta null):", loEx.Message
ENDTRY
loSB = .NULL.Ejemplo 15: Strings grandes, transferencia de datos
FoxBridge maneja strings de varios megabytes sin problemas. El bridge copia la memoria una vez en cada dirección, por lo que el tiempo escala linealmente con el tamano.
lcGrande = Replicate("X", 1024 * 1024) && 1 MB
loSB = loBridge.Create("System.Text.StringBuilder")
lnStart = Seconds()
loSB.Append(lcGrande)
? "Envio 1MB a .NET en:", Seconds() - lnStart, "seg"
lnStart = Seconds()
lcRecibido = loSB.ToString()
? "Recibo 1MB desde .NET en:", Seconds() - lnStart, "seg"
? "Longitud recibida:", Len(lcRecibido) && 1048576
? "Objetos en heap .NET:", loBridge.GetObjectCount()
loSB = .NULL.Ejemplo 16: Dictionary con valores objeto
Cuando el valor del diccionario es un objeto .NET (no un escalar), usa GetObject() para recuperarlo como proxy FoxBridge. Puedes comparar objetos por handle.
loDict = loBridge.Create("Dictionary<String, System.Text.StringBuilder>")
* Insertar un StringBuilder como valor
loSB = loBridge.Create("System.Text.StringBuilder", "Contenido inicial")
loDict.Set("doc1", loSB)
* Recuperar y modificar
loRecuperado = loDict.GetObject("doc1")
loRecuperado.Append(" — modificado!")
? loRecuperado.ToString() && "Contenido inicial — modificado!"
* Es el mismo objeto?
? loSB.GetHandle() == loRecuperado.GetHandle() && .T.
loDict = .NULL.
loSB = .NULL.
loRecuperado = .NULL.Ejemplo 17: DateTime, crear y manipular fechas
System.DateTime es el caso en el que FoxBridge NO devuelve un proxy: las fechas cruzan convertidas, así que lo que recibes es un DATETIME de VFP y lo manejas con YEAR(), MONTH() y la aritmética de siempre. En el otro sentido pasa lo mismo, y por eso puedes pasarle una fecha de VFP a un método .NET que espera un DateTime.
* System.DateTime NO cruza como proxy: FoxBridge lo convierte a un
* DATETIME de VFP (por OLE Automation Date) en los dos sentidos. Asi
* que lo que vuelve es un valor de tipo T, y se trata con las funciones
* de fecha de VFP de toda la vida.
loDt = loBridge.Static("System.DateTime")
ltAhora = loDt.Now
? "Fecha y hora:", ltAhora && un DATETIME de VFP
? "Ano:", YEAR(ltAhora)
? "Mes:", MONTH(ltAhora)
? "Dia:", DAY(ltAhora)
* La aritmetica tambien es la de VFP, en segundos
ltManana = ltAhora + 86400
* Y de vuelta: un DATETIME de VFP entra tal cual en un metodo .NET
* que espera un DateTime.
SET SAFETY OFF
STRTOFILE("prueba", "fb_dt.tmp")
loFile = loBridge.Static("System.IO.File")
loFile.SetCreationTime("fb_dt.tmp", ltManana)
loInfo = loBridge.Create("System.IO.FileInfo", "fb_dt.tmp")
? "Fecha de creacion:", loInfo.CreationTime && otro DATETIME de VFP
ERASE fb_dt.tmp
loDt = .NULL.
loFile = .NULL.
loInfo = .NULL.Ejemplo 18: Async transparente, Task.Delay
Cuando un método .NET devuelve un Task (async), FoxBridge lo espera automáticamente antes de continuar. Desde VFP parece una llamada sincrona normal.
loTask = loBridge.Static("System.Threading.Tasks.Task")
? "Llamando Task.Delay(2000) — espera 2 segundos..."
lnStart = Seconds()
loTask.Delay(2000) && FoxBridge espera automaticamente
? "Tiempo transcurrido:", Seconds() - lnStart, "seg" && ~2 seg
? "El bridge espero sin necesidad de codigo adicional"
loTask = .NULL.Ejemplo 19: HttpClient, descargar contenido web
HttpClient es una clase async de .NET. FoxBridge la hace sincrona automáticamente. Esto reemplaza WinHTTP, XMLHTTP y cualquier otra dependencia COM que uses hoy.
loHttp = loBridge.Create("System.Net.Http.HttpClient, System.Net.Http")
TRY
lcUrl = "https://httpbin.org/get"
? "Descargando:", lcUrl
lcJson = loHttp.GetStringAsync(lcUrl) && async, FoxBridge espera
? "Recibidos:", Len(lcJson), "bytes"
? "Primeros 200 chars:"
? Left(lcJson, 200)
CATCH TO loEx
? "Error de red:", loEx.Message
ENDTRY
loHttp = .NULL.Ejemplo 20: HttpClient con POST y JSON, llamar una API REST
El caso de uso más completo: construir un payload JSON con StringBuilder, enviarlo con HttpClient.PostAsync y leer la respuesta. Esto es un cliente REST completo escrito 100% en VFP.
loHttp = loBridge.Create("System.Net.Http.HttpClient, System.Net.Http")
* Construir el JSON con StringBuilder
loSB = loBridge.Create("System.Text.StringBuilder")
loSB.Append("{")
loSB.Append("""title"": ""Alta de cliente"",")
loSB.Append("""body"": ""Enviado desde VFP"",")
loSB.Append("""userId"": 1")
loSB.Append("}")
lcJson = loSB.ToString()
loSB = .NULL.
TRY
* Encoding.UTF8 es una propiedad estatica, y devuelve un OBJETO.
* Hay que pasarlo como tal: con .NULL. el Binder no encuentra el
* constructor StringContent(string, Encoding, string).
loEnc = loBridge.Static("System.Text.Encoding")
loUTF8 = loEnc.UTF8
loBody = loBridge.Create("System.Net.Http.StringContent, System.Net.Http", ;
lcJson, loUTF8, "application/json")
* POST. Es async, y FoxBridge espera la Task por ti.
loResp = loHttp.PostAsync("https://jsonplaceholder.typicode.com/posts", loBody)
* Content es un proxy; ReadAsStringAsync() tambien se espera sola.
loContent = loResp.Content
lcRespuesta = loContent.ReadAsStringAsync()
? "Respuesta del servidor:"
? lcRespuesta
loContent = .NULL.
loBody = .NULL.
loResp = .NULL.
loUTF8 = .NULL.
loEnc = .NULL.
CATCH TO loEx
? "Error:", loEx.Message
ENDTRY
loHttp = .NULL.Volver a referencia API: Referencia API ->