IR
irwinrodriguez.dev
Volver a documentación

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.

Sobre la inicialización Todos los ejemplos dan por hecho que loBridge ya está inicializado Y ACTIVADO. Sin Activate() ninguno funciona: cualquier llamada responde «FoxBridge is not activated». Ejecuta esto una sola vez al arrancar:
Crear y activar el puente (una vez al arrancar)
loBridge = NEWOBJECT("FoxBridge", "FoxBridge.prg")
IF !loBridge.Activate(lcJwt)
    ? loBridge.GetLastError()
    RETURN
ENDIF

Nivel 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.

StringBuilder: construir una cadena en .NET
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.

System.Uri: descomponer una URL en sus partes
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.

LoadAssembly: calcular el total con IVA desde tu DLL
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.
ENDIF

Nivel 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.

List<String>: añadir, recorrer y quitar elementos
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.

DirectoryInfo: nombre, tamaño y extensión de cada archivo
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().

Dictionary<String, String>: guardar, consultar y borrar claves
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.

StringBuilder.Append: una sobrecarga para cada tipo de VFP
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.

Capturar con TRY/CATCH la excepción de una URL inválida
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
ENDTRY

Ejemplo 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.

File, Guid y Environment: miembros estáticos
* 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.

Environment.CurrentDirectory: cambiar y restaurar el directorio de trabajo
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.

File.Open con FileMode y FileAccess pasados como números
* 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.

Medir 1000 llamadas seguidas a System.Math
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.

Proceso actual y su módulo principal, propiedad a propiedad
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
ENDTRY

Ejemplo 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.

.NULL. hacia .NET: una lista lo acepta, un int no
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.

Enviar y recibir 1 MB de texto entre VFP y .NET
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.

Un StringBuilder como valor de un Dictionary
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.

DateTime: fechas de .NET como DATETIME de VFP
* 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.

Task.Delay: esperar una tarea async sin código extra
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.

HttpClient: descargar una página con GET
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.

HttpClient: enviar JSON por POST a una API REST
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 ->