
Delphi Framework (Windows/Linux/Android/MacOSX/iOS) para crear fácilmente aplicaciones de escritorio, móvil y web de alto rendimiento y escalable. Delphi 10 a 12 Atenas apoyó.
¡Por favor "establezca" este proyecto en Github! No cuesta nada pero ayuda a hacer referencia al código. 
Si encuentra útil este proyecto, considere hacer una donación.
Abstracciones:
Servicios:
MVC:
Extensiones:
Extensiones MVC:
Actualizaciones:
QuickCore es un marco para construir fácilmente aplicaciones de escritorio/móvil/web.
El marco completo se basa en los pricicipios de inyección de dependencia. Un contenedor contiene todos los servicios que necesitan la aplicación, lo que permite cambios fáciles de infraestructura con un menor incort.
Los servicios se inyectan automáticamente en el servidor y se configuran desde una sola unidad "inicio". Cada proyecto central necesita una inicio.
Es una colección de servicios donde podemos registrar servicios predefinidos o personalizados y controlar su ciclo de vida (Singleton, Transitive, ...). ServiceCollection es el contenedor incorporado incluido en QuickCore y admite la inyección de constructor de forma predeterminada.
services
.AddLogging(TLoggerBuilder.GetBuilder(TLoggerOptionsFormat.ofYAML,False)
.AddConsole(procedure(aOptions : TConsoleLoggerOptions)
begin
aOptions.LogLevel := LOG_DEBUG;
aOptions.ShowEventColors := True;
aOptions.ShowTimeStamp := True;
aOptions.ShowEventType := False;
aOptions.Enabled := True;
end )
.AddFile(procedure(aOptions : TFileLoggerOptions)
begin
aOptions.FileName := ' .WebApiServer.log ' ;
aOptions.MaxFileSizeInMB := 200 ;
aOptions.Enabled := True;
end )
.Build
)
.AddDebugger
.AddOptions(TOptionsFileFormat.ofYAML,True)
// add entity database
.Extension<TEntityServiceExtension>
.AddDBContext<TShopContext>(TDBContextOptionsBuilder.GetBuilder.UseSQLite.ConnectionStringName( ' ShopContext ' ).Options)
// add Identity
.Extension<TAuthenticationServiceExtension>()
.AddIdentity<TUser,TRole>(procedure(aOptions : TIdentityOptions)
begin
aOptions.Password.RequiredLength := 6 ;
aOptions.User.RequireUniqueEmail := True;
end )
.AddEntityStore<TShopContext>();
// add Authentication
services.Extension<TAuthenticationServiceExtension>()
.AddAuthentication(procedure(aOptions : TAuthenticationOptions)
begin
end );
// add ApiKey Authentication
services.Extension<TApiKeyAuthenticationServiceExtension>
.AddApiKey()
.UseIdentityStore<TUser,TRole>( ' ApiKey ' );
// add Authorization
services.Extension<TAuthorizationServiceExtension>
.AddAuthorization(procedure(aOptions : TAuthorizationOptions)
begin
aOptions.AddPolicy( ' ApiKeyValidation ' ,TAuthorizationPolicyBuilder.GetBuilder
.RequireAuthenticatedUser.Build
// .RequireClaim(TClaimTypes.Role,'Admin').Build
);
end );Quickcore funciona con la interfaz Ilogger. Podemos usar la extensión de registro incorporada o definir su propia implementación e inyectarla.
Para usar la implementación de QuickLogger (necesita la biblioteca Quicklogger. Consulte los requisitos de instalación). Quicklogger utiliza un Ilogger Builder para una configuración fácil. Las opciones predeterminadas se pueden pasar como opciones de función delegada. Cuando existe el archivo de configuración de Quicklogger, no se aplicarán más opciones predeterminadas:
services
.AddLogging(TLoggerBuilder.GetBuilder(TLoggerOptionsFormat.ofYAML,False)
.AddConsole(procedure(aOptions : TConsoleLoggerOptions)
begin
aOptions.LogLevel := LOG_DEBUG;
aOptions.ShowEventColors := True;
aOptions.ShowTimeStamp := True;
aOptions.ShowEventType := False;
aOptions.Enabled := True;
end )
.AddFile(procedure(aOptions : TFileLoggerOptions)
begin
aOptions.FileName := ' .WebApiServer.log ' ;
aOptions.MaxFileSizeInMB := 200 ;
aOptions.Enabled := True;
end )
.Build
);... o agregar su propia implementación de registrador
services.AddLogging(MyLogger);El archivo de configuración de registro QuickCore se guarda como archivo Quicklogger.yml o json. Usando la variable de entorno Core_environment podemos definir qué uso de archivos para cada implementación. Si se define la variable de entorno, QuickCore intentará cargar/guardar "Quickcore. [Core_environment] .yaml/json" archivo.
Quickcore funciona con el patrón de opciones. Cada objeto de topación se guardará como una sección en el archivo de configuración y se puede inyectar en los constructores de servicios o controladores. El servicio de opciones debe agregar a ServiceCollection antes de que podamos agregar secciones. Podemos definir el nombre de archivo de configuración y el formato JSON o YAML.
.AddOptions(TOptionsFileFormat.ofYAML,True)Cada sección de configuración debe agregarse y se puede configurar con valores predeterminados.
services.Configure<TAppSettings>(procedure(aOptions : TAppSettings)
begin
aOptions.Smtp := ' mail.domain.com ' ;
aOptions.Email := ' [email protected] ' ;
end )
Y podemos inyectarlo más tarde tan simple como ...
constructor TMyController.Create(aLogger : ILogger; aAppSettings : IOptions<TAppSettings>);
begin
fOptions := aAppSettings. Value ;
fSMTPServer.Host := fOptions.Smtp;
end ;En la configuración de inicio puede usar opciones de lectura para hacer algunas acciones opcionales:
if services.GetConfiguration<TAppSettings>.UseCache then
begin
// do some stuff or define service implementation
end
else
begin
// do some stuff or define alternative service implementation
end ;Utilizando la variable de entorno Core_environment, podemos definir qué uso de archivos para cada implementación. Si se define la variable de entorno, QuickCore intentará cargar/guardar "Quickcore. [Core_environment] .yaml" archivo.
Si no se define las opciones. Nombre, el nombre de clase se usará como nombre de sección en el archivo de configuración. Cada opción configurada se guardará y se cargará para configurar el archivo, pero si lo queremos, podemos ocultar algunas opciones de que se hayan guardado. Use opciones. HideOptions: = true (para opciones internas no configurables externamente).
El depurador es un simple trazador-debugger (ver documentación de QuickLib). Para conectar el depurador con un servicio de registro solo necesita agregar el servicio de depuración en ServiceCollection (por defecto, utiliza una salida de consola):
services.AddDebugger;Trabajar con parámetros de línea de comandos será fácil utilizando la extensión de línea de comandos. Defina una clase heredada de tparameters o tserviceParameters (si trabaja con QuickAppServices) con sus posibles argumentos:
uses
Quick.Parameters;
type
TArguments = class (TParameters)
private
fPort : Integer;
fSilent : Boolean;
published
[ParamCommand( 1 )]
[ParamHelp( ' Define listen port ' , ' port ' )]
property Port : Integer read fPort write fPort;
property Silent : Boolean read fSilent write fSilent;
end ;Y pasar a la extensión de línea de comandos:
services.AddCommandline<TArguments>;Cuando llame a su exe con --help obtendrá documentación. Si necesita verificar un interruptor o valor, puede hacer esto:
if services.Commandline<TArguments>.Port = 0 then ...
if services.Commandline<TArguments>.Silent then ...Se pueden agregar interfaces e implementaciones a ServiceCollection. AddSingleton y AddTransient permiten definir el ciclo en vivo.
services.AddSingleton<IMyService,TMyService>;o con la creación delegada
services.AddTransient<IMyService,TMyService>(function : TMyService)
begin
Result := TMyService.Create(myparam);
Result.Host := ' localhost ' ;
end );o agregar una implementación
services.AddSingleton<TMyService>;Las extensiones son servicios inyectables que podemos agregar a nuestra aplicación/servidor. Las extensiones se inyectan en la unidad de inicio de ServiceCollection. Las extensiones del método ServiceCollection funcionan de manera similar a los métodos de extensión de .NET, extendiendo ServiceCollection.
Para agregar una extensión, necesitamos agregar su unidad a la unidad de inicio Usar cláusula (consulte las extensiones predefinidas rápidas anteriores).
uses
Quick.Core.Extensions.AutoMapper;
...
begin
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;
end ;Con QuickCore podemos crear aplicaciones web con controladores y acciones.
Cree un servidor de aplicaciones y defina el enlace y la seguridad.
ApiServer := TMvcServer.Create( ' 127.0.0.1 ' , 8080 ,False);
ApiServer.UseStartup<TStartup>;
ApiServer.Start;
```delphi
To configure services and middlewares startup must configured
```delphi
class procedure TStartup.Configure (app : TMVCServer);
begin
app
.AddControllers
.AddController(THomeController)
.DefaultRoute(THomeController, ' Home/Index ' )
.UseWebRoot( ' .wwwroot ' )
.UseRouting
.UseMVC;
end ;AddController (ControllerClass): permita agregar un controlador a un servidor de aplicaciones web.
AddControllers: agregue todos los controladores registrados durante su unidad de inicialización con RegisterController (controlerClass);
Usewebroot (ruta): define archivos estáticos/carpeta de datos.
USECUSTOMERRORPAGES: Habilite el uso de páginas de error personalizadas. En un error 403, el servidor buscará archivos 403.html, 40x.html o 4xx.html. Si se especifica la página de Dinamic, los patrones simples de bigote se reemplazarán con información de error (StatusCode, Statusmsg, etc.).
USEMUSTACHEPAGES: Simple Motor de plantilla de bigote para reemplazar vistas simples.
Middlewares son como capas de funcionalidad y se ejecutan en una tubería de solicitud. Cada solicitud de solicitud para cada MidDLWares (en orden de creación) o no, dependiendo de los requisitos de Middelware.
USESTATICFILES: para permitir el contenido estático de servir.
UseHSTS: HTTP Strict Transport Security Middleware para permitir solo conexiones HTTPS.
UseHttPsRedirection: habilita la redirección middleware para redirigir en la ubicación del encabezado encontrada.
UserOuting: Permite enriquecer el middleware para obtener la ruta coincidente desde la solicitud.
USEMVC: Habilite MVC Middleware para administrar y redirigir cada solicitud a la acción o vista del controlador corresponsal.
USEMIDDleware: para agregar clase de middleware personalizada para solicitar la tubería.
Use (requestDelegate): ejecute un método anónimo como un middleware.
UseAuthentication: intenta obtener información de autenticación de una solicitud.
UseAuthorización: permita/no permita los accesorios a los recursos basados en las políticas de autorización.
Cada controlador herede del controlador de control y los métodos publicados se convierte en acciones. Con atributos personalizados podemos definir el enrutamiento, la autorización, etc. de estos métodos. Como todos los controladores se inyectan de la inyección de dependencia, podemos definir el constructor con parámetros autoinjectables y el COI tratará de resolver en la creación del constructor.
constructor THomeController.Create(aLogger: ILogger);El enrutamiento HTTP se basa en atributos personalizados. Necesitamos definir el enrutamiento para cada controlador y método/acción.
[HttpGet( ' home/index ' )]
function THomeController.Index : IActionResult;
[HttpPost( ' home/GetAll ' )]
function THomeController.GetAll : IActionResult;Si el enrutamiento se define en clase, entonces es global y no necesita ser replicado en cada método/acción:
[Route( ' home/other ' )]
THomeController = class (THttpController)
published
[HttpPost( ' GetAll ' )] // global + local = home/other/GetAll
function THomeController.GetAll : IActionResult;Los parámetros se definen con atributos y se analizan e inyectan automáticamente como parámetros de método.
[HttpGet( ' Add/{productname}/{price} ' )]
function Add ( const ProductName : string; Price : Integer): IActionResult;Los parámetros se pueden escribir definidos. INT: solo alfa numérico: solo letras. FLOAT: Solo números flotantes.
[HttpGet( ' Add/{productname:alpha}/{price:float} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Un ? Definir un parámetro como opcional
[HttpGet( ' Add/{productname:alpha}/{price:float?} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Para obtener un parámetro del cuerpo de solicitud (con deserialización automática)
[HttpPost( ' Add/User ' )]
function Add ([FromBody] User : TUser): IActionResult;Los resultados de la acción son los resultados de un controlador. Statuscode (statuscode, statusText): devuelve un código de estado y texto de estado opcional al cliente.
Result := StatusCode( 200 , ' ok ' );OK (StatusText): Devuelve un código de estado 200 y StatusText opcional.
Aceptado (StatusText): devuelve un código de estado 202 y un texto de estado opcional.
BadRequest (StatusText): devuelve un código de estado 400 y texto de estado opcional.
NotFound (StatusText): devuelve un código de estado 404 y un texto de estado opcional.
Forbid (StatusText): devuelve un código de estado 403 y un texto de estado opcional.
No autorizado (StatusText): devuelve un código de estado 401 y un texto de estado opcional.
Redirección (URL): Devuelve una redirección temporal a la URL.
Redirectpermament (URL): Devuelve una redirección permanente a la URL.
Contenido (texto): Devuelve un texto de respuesta.
JSON (Object, OnlyPublishedProperties): Devuelve un objeto o lista JSON serializado. Si solo se habilitan las Propultias de Publicado, solo se serializarán las propiedades publicadas de objetos.
Result := Json(User);Ver (ViewName): devuelve una vista.
Result := View ( ' home ' );Automapper Extension permite que MAP sea un tipo de clase a otro tipo de clase. Para usar AUTOMAPPER, debemos agregar servicio a ServiceCollection en la unidad de estatuto:
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;Luego defina los mapas de perfil con la relación de mapeo. Si los nombres de las propiedades son idénticos, no deberíamos tener que proporcionar manualmente una asignación:
constructor TMyProfile.Create;
begin
// maps properties with same name in both classes
CreateMap<TDBUser,TUser>();
end ;
initialization
TAutoMapper.RegisterProfile<TMyProfile>;Si algunas propiedades tienen un nombre o tipo diferente, debemos usar asignaciones personalizadas:
constructor TMyProfile.Create;
begin
// maps properties with delegate function and rest maps formember
CreateMap<TDBProduct,TProduct>(procedure(src : TDBProduct; tgt : TProduct)
begin
tgt.Id := src.uid;
tgt.Age := src.Age;
end )
.ForMember( ' Money ' , ' Cash ' )
.ForMember( ' Name ' , ' FullName ' )
.IgnoreOtherMembers;
end ;
initialization
TAutoMapper.RegisterProfile<TMyProfile>;Formember (SourceProperty, TargetProperty): asigna un nombre de propiedad de origen a un nombre de propiedad de destino. IgnoreAllnonexisting: Ignore todas las propiedades no existentes en el objetivo.
IgnoreotherMBers: solo se resolverán las propiedades definidas en el mapeo personalizado.
ResolveUnMapped: intenta resolver automáticamente cualquier mapa sin un ProfilEmap definido.
El servicio automático se puede inyectar en un objeto/controlador que define la abstracción en las cláusulas de usos.
uses
Quick.Core.Mapping.Abstractions;
...
TMyController.Create(aMapper : IMapper);.. y úsalo:
product := fMapper.Map(dbproduct).AsType<TProduct>;¿Quieres aprender Delphi o mejorar tus habilidades? Learndelphi.org