
Delphi Framework (Windows/Linux/Android/Macosx/iOS) para criar aplicativos de desktop, móveis e web de alto desempenho e escalonáveis com facilidade. Delphi 10 a 12 Atenas apoiado.
Por favor, "estrela" este projeto no Github! Custa nada além de ajuda a fazer referência ao código. 
Se você achar esse projeto útil, considere fazer uma doação.
Abstrações:
Serviços:
MVC:
Extensões:
Extensões MVC:
Atualizações:
O QuickCore é uma estrutura para fácil construir aplicativos para desktop/celular/web.
A estrutura inteira é baseada em pricípios de injeção de dependência. Um contêiner detém todos os serviços necessários para o aplicativo, permitindo alterações fáceis de infraestrutura com um menor enriquecimento.
Os serviços são injetados automaticamente no servidor e configurados em uma única unidade "startup". Todo projeto principal precisa de uma startup.PAS com uma classe herdando do TSTARTUPBASE (consulte Exemplos na pasta de amostras).
É uma coleção de serviços onde podemos registrar serviços predefinidos ou personalizados e controlar seu ciclo de vida (Singleton, Transiente, ..). O ServiceCollection é o contêiner de construção incluído no Quickcore e suporta a injeção do construtor por padrão.
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 );O Quickcore trabalha com a interface ilogger. Podemos usar a extensão de registro de construção ou definir a própria implementação e injetar-a.
Para usar a implementação do QuickLogger (precisa da Biblioteca QuickLogger. Consulte os requisitos de instalação). O QuickLogger usa um construtor de ILogger para facilitar a configuração. As opções padrão podem ser passadas como função delegada de opções. Quando o arquivo de configuração do QuickLogger existe, nenhuma opção padrão será aplicada mais:
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
);... ou adicione a própria implementação de madeireiro
services.AddLogging(MyLogger);O arquivo de configuração de log do QuickCore é salvo como o arquivo quicklogger.yml o json. Usando a variável de ambiente Core_environment, podemos definir o uso do arquivo para cada implementação. Se a variável de ambiente estiver definida, o QuickCore tentará carregar/salvar o arquivo "QuickCore. [Core_environment] .yaml/json".
O Quickcore trabalha com o padrão de opções. Todo objeto de tópicos será salvo como uma seção no arquivo de configuração e pode ser injetado em serviços de serviços ou controladores. O serviço de opções precisa adicionar ao ServiceCollection antes que possamos adicionar seções. Podemos definir o nome do arquivo de configuração e o formato JSON ou YAML.
.AddOptions(TOptionsFileFormat.ofYAML,True)Cada seção de configuração precisa ser adicionada e pode ser configurada com valores padrão.
services.Configure<TAppSettings>(procedure(aOptions : TAppSettings)
begin
aOptions.Smtp := ' mail.domain.com ' ;
aOptions.Email := ' [email protected] ' ;
end )
E podemos injetar mais tarde, tão simples quanto ...
constructor TMyController.Create(aLogger : ILogger; aAppSettings : IOptions<TAppSettings>);
begin
fOptions := aAppSettings. Value ;
fSMTPServer.Host := fOptions.Smtp;
end ;No Startup Config, você pode usar as opções de leitura para executar algumas ações opcionais:
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 ;Usando a variável de ambiente Core_environment, podemos definir o uso do arquivo para cada implementação. Se a variável de ambiente estiver definida, o QuickCore tentará carregar/salvar o arquivo "Quickcore. [Core_environment] .Yaml".
Caso contrário, o nome da classe é definido, o nome da classe será usado como nome da seção no arquivo de configuração. Toda opção configurada será salvar e carregar no arquivo de configuração, mas, se quiser, podemos ocultar algumas opções da salva. Use Options.Hideoptions: = true (para opções internas não configuráveis externamente).
O depurador é um traçador simples (consulte a documentação do Quicklib). Para conectar o depurador com um serviço de registro, só precisa adicionar serviço depurador no ServiceCollection (por padrão, usa uma saída do console):
services.AddDebugger;Trabalhar com os parâmetros de linha de comando será fácil usando a extensão de comando. Defina uma classe herdada de TParameters ou TServiceParameters (se estiver trabalhando com QuickAppservices) com seus possíveis 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 ;E passe para a extensão de linha de comando:
services.AddCommandline<TArguments>;Quando você liga para o seu exe com -Help, você recebe documentação. Se você precisar verificar se uma opção ou valor, pode fazer assim:
if services.Commandline<TArguments>.Port = 0 then ...
if services.Commandline<TArguments>.Silent then ...Interfaces e implementações podem ser adicionadas ao ServiceCollection. Addsingleton e addtransient permitem definir o ciclo ao vivo.
services.AddSingleton<IMyService,TMyService>;ou com criação delegada
services.AddTransient<IMyService,TMyService>(function : TMyService)
begin
Result := TMyService.Create(myparam);
Result.Host := ' localhost ' ;
end );ou adicione uma implementação
services.AddSingleton<TMyService>;As extensões são serviços injetáveis que podemos adicionar ao nosso aplicativo/servidor. As extensões são injetadas na unidade de inicialização do ServiceCollection. As extensões do método do ServiceCollection funcionam de maneira semelhante aos métodos de extensão .NET, estendendo o serviço de serviço.
Para adicionar uma extensão, precisamos adicionar sua unidade à unidade de inicialização usa a cláusula (consulte Extensões predefinidas do Quickcore acima).
uses
Quick.Core.Extensions.AutoMapper;
...
begin
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;
end ;Com o Quickcore, podemos criar aplicativos da Web com controladores e ações.
Crie um servidor de aplicativos e defina a ligação e a segurança.
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 (ControlClass): permita que adicione um controlador a um servidor de aplicativos da Web.
AddControllers: Adicione todos os controladores registrados durante sua unidade de inicialização com o RegisterController (ControlClass);
Usewebroot (caminho): defina arquivos estáticos/pasta de dados.
USECUSTOMERRORPAGES: Ative o uso de páginas de erro personalizadas. Em um erro 403, o servidor procurará arquivos 403.html, 40x.html ou 4xx.html. Se a página dinâmica especificada, os padrões simples de bigode serão substituídos por informações de erro (statusCode, statusmsg, etc).
UsoMustachePages: Motor de modelo de bigode simples para substituir as vistas simples.
Middlewares são como camadas de funcionalidade e entra em um pipeline de solicitação. Cada passagem de solicitação para cada Middlwares (em ordem de criação) ou não, dependendo dos requisitos de middelware.
UsestaticFiles: para permitir o conteúdo estático de servir.
Usehsts: http rigoroso middleware de segurança de transporte para permitir apenas conexões HTTPS.
UsehttpsRedirection: Permite que o middleware de redirecionamento redirecionasse no local do cabeçalho encontrado.
Usuário: Permite que o middleware de roteamento obtenha a rota correspondente da solicitação.
UsoMVC: Ative o middleware MVC para gerenciar e redirecionar todas as solicitações para sua ação ou visualização do controlador correspondente.
UsoMiddleware: para adicionar aula de middleware personalizada para solicitar o pipeline.
Use (requestDelegate): Execute um método anônimo como middleware.
UseAuthentication: tenta obter informações de autenticação de uma solicitação.
UseAtorização: Permitir/proibir acessos a recursos com base nas políticas de autorização.
Todo controlador herda do thttpController e métodos publicados se torna ações. Com atributos personalizados, podemos definir roteamento, autorização, etc. desses métodos. Como todos os controladores são injetados da injeção de dependência, podemos definir o construtor com parâmetros autoinjetáveis e o COI tentará resolver a criação do construtor.
constructor THomeController.Create(aLogger: ILogger);O roteamento HTTP é baseado em atributos personalizados. Precisamos definir o roteamento para cada controlador e método/ação.
[HttpGet( ' home/index ' )]
function THomeController.Index : IActionResult;
[HttpPost( ' home/GetAll ' )]
function THomeController.GetAll : IActionResult;Se o roteamento definido na aula, é global e não precisará ser replicado em cada método/ação:
[Route( ' home/other ' )]
THomeController = class (THttpController)
published
[HttpPost( ' GetAll ' )] // global + local = home/other/GetAll
function THomeController.GetAll : IActionResult;Os parâmetros são definidos com atributos e analisados automaticamente e injetados como parâmetros do método.
[HttpGet( ' Add/{productname}/{price} ' )]
function Add ( const ProductName : string; Price : Integer): IActionResult;Os parâmetros podem ser digitados definidos. INT: Numérico apenas Alpha: apenas letras. FLOAT: Apenas números flutuantes.
[HttpGet( ' Add/{productname:alpha}/{price:float} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Um ? Defina um parâmetro como opcional
[HttpGet( ' Add/{productname:alpha}/{price:float?} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Para obter um parâmetro do corpo de solicitação (com desserialização automática)
[HttpPost( ' Add/User ' )]
function Add ([FromBody] User : TUser): IActionResult;Os resultados da ação são resultados de um controlador. StatusCode (StatusCode, Statustext): Retorna um código de status e texto de status opcional ao cliente.
Result := StatusCode( 200 , ' ok ' );OK (STATUSTIXEXT): Retorna um código de status de 200 e o Statustext opcional.
Aceito (STATUSTIXEXT): Retorna um código de status 202 e texto de status opcional.
BadRequest (Statustext): Retorna um código de status de 400 e texto de status opcional.
NOTFOND (STATUSTUSTEXT): Retorna um código de status 404 e texto de status opcional.
Proibir (Statustustext): Retorna um código de status 403 e texto de status opcional.
Não autorizado (STATUSTIXEXT): Retorna um código de status 401 e texto de status opcional.
Redirecionar (URL): retorna um redirecionamento temporal ao URL.
RedirectPermament (URL): retorna um redirecionamento permanente ao URL.
Conteúdo (texto): retorna um texto de resposta.
JSON (Objeto, apenas PublicadoProperties): Retorna um objeto ou lista JSON serializada. Se apenas oPublishedProperties habilitadas, apenas as propriedades publicadas pelo objeto serão serializadas.
Result := Json(User);View (ViewName): retorna uma visualização.
Result := View ( ' home ' );A extensão do AutomApper permite mapa um tipo de classe para outro tipo de classe. Para usar o AutomApper, devemos adicionar serviço ao ServiceCollection na unidade de status:
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;Em seguida, defina mapas de perfil com o relacionamento de mapeamento. Se os nomes das propriedades forem idênticos, não devemos fornecer manualmente um mapeamento:
constructor TMyProfile.Create;
begin
// maps properties with same name in both classes
CreateMap<TDBUser,TUser>();
end ;
initialization
TAutoMapper.RegisterProfile<TMyProfile>;Se algumas propriedades tiverem nome ou tipo diferente, devemos usar mapeamentos personalizados:
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): mapeia um nome de propriedade de origem para um nome de propriedade de destino. Ignoreeallnonexisting: ignore todas as propriedades não existentes no alvo.
IgnoreotherMembers: Somente propriedades definidas no mapeamento personalizado serão resolvidas.
ResolvaNmapped: tenta resolver automaticamente qualquer mapa sem um Profilemap definido.
O serviço AutomApper pode ser injetado em um objeto/controlador que define a abstração nas cláusulas de usos.
uses
Quick.Core.Mapping.Abstractions;
...
TMyController.Create(aMapper : IMapper);..e use -o:
product := fMapper.Map(dbproduct).AsType<TProduct>;Você quer aprender Delphi ou melhorar suas habilidades? LearnDelphi.org