La familia de aplicaciones — Guía de uso
🌍 Idioma: English | Español
Una aplicación DAF es una de cuatro variantes montadas sobre el host genérico. Esta guía cubre lo que comparten: cuál es la tuya, qué añade la capa sobre el host, a qué corresponde en .NET y dónde fueron a parar los puntos de entrada que la precedieron.
Índice
- Cuál es tu punto de entrada
- Qué se retiró, y dónde fue a parar
- Qué añade la capa de aplicación sobre el host
- Qué es esta capa, en términos de .NET
Cuál es tu punto de entrada
Hay uno por variante de aplicación, y elegir es cuestión de qué tipo de aplicación estás escribiendo — no de cuál de dos capas usar. Una VCL entera, con sus propias specs, es TicTacToeApp:
| Tu aplicación | Punto de entrada | Vive en | Build devuelve |
|---|---|---|---|
| Consola / herramienta CLI | TCliApplication.CreateBuilder(Args) + B.ParseArgs(Args) |
Daf.Cli |
ICliApplication |
| Web | TWebApplication.CreateBuilder(Args) |
Daf.Web |
IWebApplication |
| Escritorio, VCL | TVclApplication.CreateBuilder |
Daf.VCL |
IVclApplication |
| Escritorio, FireMonkey | TFmxApplication.CreateBuilder |
Daf.FMX |
IFmxApplication |
Las cuatro comparten Services, Configuration, Environment, Logging, Properties y ServiceProviderOptions, escritos igual. Ese contrato común —IHostApplicationBuilder— es lo que las hace una familia y no cuatro cosas parecidas, y es lo que permite que un paquete aporte registros de arranque sin saber qué variante lo va a consumir.
Se parten en dos por quién es dueño del bucle: en CLI y Web, DAF es dueño del proceso y Run arranca, trabaja y para, así que el .dpr acaba cuando Run acaba. En VCL y FMX el message loop ya existe y es de Vcl.Forms.Application / FMX.Forms.Application; la variante crea el formulario principal y delega. Son dos contratos de ciclo de vida, no cuatro variaciones de uno.
Qué se retiró, y dónde fue a parar
| Antes | Ahora |
|---|---|
THostBuilder.Create.ConfigureServices(...) |
B.Services.… en el builder de cualquier variante — el estilo diferido se retiró; queda uno, el inmediato |
IHostBuilder |
IHostApplicationBuilder, el contrato común de la familia. THostBuilder sobrevive entero como detalle de implementación |
TDafApplication / TDafApplicationBuilder |
retirados en 2.0. Su relevo es la variante, de la tabla de arriba |
TDafApplication.CreateHostBuilder |
el CreateBuilder de tu variante |
IDafApplication |
la I…Application que devuelve el Build de tu variante |
TDafApplication.RunAsync |
Run. Era la misma llamada con otro nombre — Delphi no tiene async/await con el que hacerla otra cosa |
TDafApplication.VersionRequested |
IParseResult.IsVersionRequested — la gramática contesta --version, y la comprobación escrita a mano se retira en vez de mudarse |
TDafApplication.App |
DafApp, solo en VCL y FMX. CLI y Web no tienen global a propósito |
Daf.Application.Version |
Daf.Commons — las cuatro variantes alcanzan ahí TVersionInfo y [Version]. Debug es de solo lectura y lo declara el binario, y VersionTag recibe una plantilla |
Qué añade la capa de aplicación sobre el host
El host te da el contenedor, la configuración, los servicios alojados y las tareas de arranque. Encima de eso, las variantes añaden el borde alrededor del Run — que es la parte que cada .dpr se escribía a mano:
| Qué | Dónde | Qué variantes |
|---|---|---|
| Decidir si el proceso llega a arrancar | SingleInstance(Id) |
CLI, VCL, FMX |
| La política de lo que se escapa, y el código de salida | OnException(Policy) |
CLI, Web |
Pasarle a esa política lo que se escapa antes del Run |
HandleException(E), en el except del .dpr |
CLI, Web |
| La acción del comando alcanzado, y su código de salida | SetAction(Action) / SetAction(Command, Action) |
CLI |
--version, --help, invocación inválida |
RootCommand, contestado por el parse de lo que recibe B.ParseArgs(Args) |
CLI |
| El servidor HTTP, cableado a DI y al host | WebApp.AddHttpServer + MapControllers |
Web |
| Crear el formulario principal y entregar el bucle | Run(TFormClass) |
VCL, FMX |
| Un global para el código que la plataforma construye sola | DafApp |
VCL, FMX |
Dos miembros de la familia de .NET no se portan, y quedan declarados en vez de descubiertos: Metrics, porque no hay pieza equivalente en DAF a la que apuntar, y ConfigureContainer<T>, porque una interfaz de Delphi no admite métodos genéricos — no es que se descarte, es que no es expresable. Las opciones del proveedor por defecto, que .NET fija a través de ese miembro, son la ServiceProviderOptions del builder.
Qué es esta capa, en términos de .NET
Casi todos los módulos de DAF portan algo de Microsoft.Extensions.*, y este parece no portar nada —no existe Microsoft.Extensions.Application—. El equivalente sí existe, solo que en otra parte del mismo ecosistema: es la familia de constructores de aplicación montada sobre el host genérico: HostApplicationBuilder, WebApplicationBuilder, MauiAppBuilder. Cada uno empareja un builder con un objeto de aplicación construido (WebApplication, MauiApp) que posee el host en vez de serlo. El CreateBuilder de cada variante y la I…Application que construye son ese par.
La familia tiene cuatro miembros donde .NET tiene tres, y el de más no es un concepto de más: Delphi tiene dos stacks de interfaz, así que escritorio son VCL y FMX en vez de una sola entrada.
Donde diverge, y esto importa más que el parecido:
- Delphi no tiene métodos de extensión, y en .NET toda la superficie de composición lo es.
AddJsonFile,AddHostedService,UseSerilog,ConfigureKestrel: todos son extensiones que aporta el paquete dueño de la funcionalidad, y así es como .NET deja crecer un builder sin que el builder sepa de nada. Delphi tiene class helpers, pero solo uno está en ámbito por tipo y ninguno se aplica a interfaces, así que el truco no se traslada. DAF compone con fachadas explícitas —JsonConfig.AddFile(Builder, …)en vez deBuilder.AddJsonFile(…)— y con unIServiceCollectionque es un record con métodos de verdad. - Las fuentes por defecto son las de .NET 10, con tres diferencias. El builder carga
appsettings.json,appsettings.{Entorno}.json,{ApplicationName}.settings.json,{ApplicationName}.settings.{Entorno}.json, todas las variables de entorno y la línea de comandos, comoHost.CreateApplicationBuilder, y deriva el entorno y el content root de la misma manera —las variables del propio host llevanDAF_donde las de .NET llevanDOTNET_, así queDAF_ENVIRONMENTesenvironment—. Lo que difiere: no hay user secrets; los ficheros no se recargan cuando cambian; y una variable de entorno con un prefijo de cadena de conexión comoSQLCONNSTR_no se convierte en una claveConnectionStrings:. - Sin proveedor de log por defecto. .NET escribe en la consola, en la salida de depuración y en el event source salvo que se le diga otra cosa; DAF no añade ninguno. Quien usa
Loggingañade un proveedor, oAddNullProviderpara declarar que el silencio es a propósito: conLoggingusado y sin proveedor,Buildfalla conELoggingCompositionError. Propertiesva por clave de cadena,TDictionary<string, TValue>, donde .NET usaobject.- El arranque es sincrónico de principio a fin. El
RunAsync,StartAsyncyStopAsyncde .NET no tienen contrapartida aquí;Run,StartyStopvuelven cuando el trabajo está hecho.
Ver también
- 📖 Hosting — Guía de uso — el host genérico sobre el que se montan las cuatro variantes
- 📖 Composición del arranque — las dos fases y las reglas de orden