
Delphi Framework (Windows/Linux/Android/macOSX/iOS), um leistungsstarke und skalierbare Desktop-, Mobil- und Webanwendungen aufzubauen. Delphi 10 bis 12 Athen unterstützt.
Bitte "Star" dieses Projekt in GitHub! Es kostet nichts anderes, als auf den Code zu verweisen. 
Wenn Sie dieses Projekt nützlich finden, erwägen Sie bitte eine Spende.
Abstraktionen:
Dienstleistungen:
MVC:
Erweiterungen:
MVC -Erweiterungen:
Aktualisierungen:
QuickCore ist ein Framework zum einfachen Bau von Desktop-/Mobil-/Web -Apps.
Der gesamte Rahmen basiert auf Abhängigkeitsinjektionspriden. Ein Container enthält alle von der Anwendung benötigten Dienste, sodass sich einfache Änderungen in der Infrastruktur mit einem geringfügigen Eingang ermöglichen.
Dienste werden automatisch in den Server eingefügt und aus einem "Startup" ein Einheit konfiguriert. Jedes Kernprojekt benötigt ein Startup.pas mit einer Klasse, die von TStartUpbase erbt (siehe Beispiele zum Samples -Ordner).
Es handelt sich um eine Sammlung von Diensten, bei denen wir vordefinierte oder benutzerdefinierte Dienste registrieren und ihren Lebenszyklus (Singleton, Transient, ..) steuern können. Servicehollektion ist der in QuickCore enthaltene Gebäudebehälter und unterstützt standardmäßig die Konstruktorinjektion.
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 funktioniert mit Iloogger Interface. Wir können eine Build-In-Protokollierungserweiterung verwenden oder die eigene Implementierung definieren und injizieren.
Um die QuickLogger -Implementierung zu verwenden (benötigt die QuickLogger -Bibliothek. Siehe Installationsanforderungen). QuickLogger verwendet einen Iloogger Builder für eine einfache Konfiguration. Standardoptionen können als Optionsdelegierfunktion übergeben werden. Wenn die QuickLogger -Konfigurationsdatei vorliegt, werden keine Standardoptionen angewendet:
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
);... oder eine eigene Logger -Implementierung hinzufügen
services.AddLogging(MyLogger);Die QuickCore -Protokollierungs -Konfigurationsdatei wird als QuickLogger.yml o JSON -Datei gespeichert. Mithilfe der Variablen um Core_Environment -Umgebungen können wir definieren, welche Dateien für jede Implementierung verwendet werden. Wenn die Umgebungsvariable definiert ist, versucht QuickCore, "QuickCore" zu laden/zu speichern. [Core_environment] .yaml/json "-Datei.
QuickCore funktioniert mit Optionsmuster. Jedes Tops -Objekt wird als Abschnitt in der Konfigurationsdatei gespeichert und kann in Dienste oder Controller -Konstruktoren injiziert werden. Der Optionsservice muss zu ServicEcollection hinzugefügt werden, bevor wir Abschnitte hinzufügen können. Wir können den Konfigurations -Dateiname und das JSON- oder YAML -Format definieren.
.AddOptions(TOptionsFileFormat.ofYAML,True)Jeder Konfigurationsabschnitt muss hinzugefügt werden und kann mit Standardwerten konfiguriert werden.
services.Configure<TAppSettings>(procedure(aOptions : TAppSettings)
begin
aOptions.Smtp := ' mail.domain.com ' ;
aOptions.Email := ' [email protected] ' ;
end )
Und wir können es später so einfach injizieren wie ...
constructor TMyController.Create(aLogger : ILogger; aAppSettings : IOptions<TAppSettings>);
begin
fOptions := aAppSettings. Value ;
fSMTPServer.Host := fOptions.Smtp;
end ;In Startup -Konfiguration können Sie Leseoptionen verwenden, um einige optionale Aktionen auszuführen:
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 ;Mithilfe der Variablen um Core_Environment -Umgebungen können wir definieren, welche Dateien für jede Implementierung verwendet werden. Wenn die Umgebungsvariable definiert ist, versucht QuickCore, "QuickCore" zu laden/zu speichern. [Core_environment] .yaml "-Datei.
Wenn nicht Optionen.Name definiert ist, wird der Klassenname als Abschnittsname in der Konfigurationsdatei verwendet. Jede konfigurierte Option wird gespeichert und in die Konfigurationsdatei geladen. Wenn wir möchten, können wir jedoch einige Optionen ausblenden, wenn wir gespeichert wurden. Verwenden Sie Optionen. Hidesoptions: = True (für interne Optionen, die nicht extern konfigurierbar sind).
Debugger ist ein einfacher Tracer-Debugger (siehe QuickLib-Dokumentation). Um Debugger mit einem Protokollierungsdienst zu verbinden, muss nur Debugger -Service in serviceCollection hinzugefügt werden (standardmäßig verwendet eine Konsolenausgabe):
services.AddDebugger;Die Arbeit mit Befehlsleitungsparametern ist einfach, wenn Sie die Befehlszeilenerweiterung verwenden. Definieren Sie eine Klasse, die von TPARAMETERS oder TServiceParameters (bei der Arbeit mit QuickAppServices) mit Ihren möglichen Argumenten geerbt wurde:
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 ;Und an die DE -Befehlszeile -Erweiterung weitergeben:
services.AddCommandline<TArguments>;Wenn Sie Ihr Exe mit -Help anrufen, erhalten Sie eine Dokumentation. Wenn Sie nach einem Switch oder einem Wert suchen müssen, können Sie dies mögen:
if services.Commandline<TArguments>.Port = 0 then ...
if services.Commandline<TArguments>.Silent then ...Schnittstellen und Implementierungen können zur Servicehollektion hinzugefügt werden. AddSingleton und Addtransient erlauben Live -Zyklus.
services.AddSingleton<IMyService,TMyService>;oder mit delegierter Schöpfung
services.AddTransient<IMyService,TMyService>(function : TMyService)
begin
Result := TMyService.Create(myparam);
Result.Host := ' localhost ' ;
end );oder eine Implementierung hinzufügen
services.AddSingleton<TMyService>;Erweiterungen sind injizierbare Dienste, die wir zu unserer App/Server hinzufügen können. Erweiterungen werden in die Starteinheit für die Servicehollektion injiziert. Die Erweiterungen der Servicehollektion Methode funktioniert ähnlich wie .NET -Erweiterungsmethoden, Erweiterung der Servicehollektion.
Um eine Erweiterung hinzuzufügen, müssen wir die Einheit der Starteinheit verwenden, die Klausel verwendet (siehe oben definierte Erweiterungen von QuickCore).
uses
Quick.Core.Extensions.AutoMapper;
...
begin
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;
end ;Mit QuickCore können wir Webanwendungen mit Controllern und Aktionen erstellen.
Erstellen Sie einen Anwendungsserver und definieren Sie Bindungen und Sicherheit.
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): Ermöglichen Sie einem Web -App -Server einen Controller.
AddController: Fügen Sie alle während ihrer Initialisierungseinheit registrierten Controller mit RegisterController (ControllerClass) hinzu.
UseWebroot (Pfad): Definieren Sie den statischen Dateien/Datenordner.
UsecustomErrorPages: Aktivieren Sie die Verwendung benutzerdefinierter Fehlerseiten. Bei einem 403 -Fehler sucht der Server nach einem 403.html, 40x.html oder 4xx.html -Dateien. Wenn die dinamische Seite angegeben ist, werden einfache Schnurrbartmuster durch Fehlerinformationen (Statuscode, StatusMSG usw.) ersetzt.
UsemustachePages: Einfache Schnurrbartvorlage -Engine, um einfache Ansichten zu ersetzen.
Middlewares sind wie Funktionsschichten und läuft in eine Anforderungspipeline. Jede Anfrage für jede Zwischenzeit (in Erstellungsreihenfolge) oder nicht, abhängig von Middelware -Anforderungen.
UsestaticFiles: Damit statische Inhalte dienen.
UseHSTS: HTTP Strict Transport Security Middleware, um nur HTTPS -Verbindungen zu ermöglichen.
UsehttpsRection: Ermöglicht die Umleitung Middleware, um den gefundenen Kopfzeilenort zu leiten.
Benutzerouting: Ermöglicht das Routing Middleware, eine passende Route von der Anfrage abzurufen.
UsemVC: MVC Middleware aktivieren, um jede Anforderung an seine Korrespondenz -Controller -Aktion oder -ansicht zu verwalten und umzuleiten.
Usemiddleware: Um eine benutzerdefinierte Middleware -Klasse hinzuzufügen, um Pipeline anzufordern.
Verwendung (RequestDelegate): Führen Sie eine anonyme Methode als Middleware aus.
UseAuthentication: Versucht, Authentifizierungsinformationen von einer Anfrage zu erhalten.
UseAuthorisierung: Erlauben/Verlassen von Klagen auf Ressourcen, die auf Autorisierungsrichtlinien basieren.
Jeder Controller ineriten von ThttpController und veröffentlichte Methoden werden zu Aktionen. Mit benutzerdefinierten Attributen können wir Routing, Autorisierung usw. dieser Methoden definieren. Da alle Controller aus der Abhängigkeitsinjektion injiziert werden, können wir den Konstruktor mit autoinjektierbaren Parametern definieren, und IOC wird versuchen, die Erstellung von Konstruktoren aufzulösen.
constructor THomeController.Create(aLogger: ILogger);Das HTTP -Routing basiert benutzerdefinierte Attribute. Wir müssen das Routing für jeden Controller und jede Methode/Aktion definieren.
[HttpGet( ' home/index ' )]
function THomeController.Index : IActionResult;
[HttpPost( ' home/GetAll ' )]
function THomeController.GetAll : IActionResult;Wenn das Routing in der Klasse definiert ist, ist es global und muss nicht auf jeder Methode/Aktion repliziert werden:
[Route( ' home/other ' )]
THomeController = class (THttpController)
published
[HttpPost( ' GetAll ' )] // global + local = home/other/GetAll
function THomeController.GetAll : IActionResult;Parameter werden mit Attributen definiert und automatisch analysiert und als Methodenparameter injiziert.
[HttpGet( ' Add/{productname}/{price} ' )]
function Add ( const ProductName : string; Price : Integer): IActionResult;Parameter können definiert werden. INT: Numerisch nur Alpha: Nur Buchstaben. Float: Nur schwimmende Zahlen.
[HttpGet( ' Add/{productname:alpha}/{price:float} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Ein ? Definieren Sie einen Parameter als optional
[HttpGet( ' Add/{productname:alpha}/{price:float?} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;Um einen Parameter aus der Anforderungskörper zu erhalten (mit automatischer Deserialisierung)
[HttpPost( ' Add/User ' )]
function Add ([FromBody] User : TUser): IActionResult;Aktionsergebnisse sind Ergebnisse eines Controllers. StatusCode (StatusCode, StatuStext): Gibt einen Statuscode und einen optionalen Statustext an den Client zurück.
Result := StatusCode( 200 , ' ok ' );OK (StatuStext): Gibt einen 200 -Status -Code und einen optionalen StatuStext zurück.
Akzeptiert (StatuStext): Gibt einen 202 Statuscode und einen optionalen Statustext zurück.
BadRequest (StatuStext): Gibt einen 400 -Statuscode und einen optionalen Statustext zurück.
NotFound (StatuStext): Gibt einen 404 -Statuscode und einen optionalen Statustext zurück.
Verbot (StatuStext): Gibt einen 403 -Statuscode und einen optionalen Statustext zurück.
Nicht autorisiert (StatuStext): Gibt einen 401 -Statuscode und einen optionalen Statustext zurück.
Umleitung (URL): Gibt eine zeitliche Umleitung in URL zurück.
RedirectPermament (URL): Gibt eine dauerhafte Umleitung in URL zurück.
Inhalt (Text): Gibt einen Antworttext zurück.
JSON (Objekt, nur veröffentlichte Properties): Gibt ein serialisiertes JSON -Objekt oder eine serialisierte JSON -Liste zurück. Wenn nur veröffentlichte Properties aktiviert sind, werden nur von Objekt veröffentlichte Eigenschaften serialisiert.
Result := Json(User);View (ViewName): Gibt eine Ansicht zurück.
Result := View ( ' home ' );Die Automapper -Erweiterung ermöglicht die Zuordnung eines Klassentyps zu einem anderen Klassentyp. Um Automapper zu verwenden, müssen wir ServicEcollection in der Statup -Einheit Service hinzufügen:
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;Definieren Sie dann Profilkarten mit Mapping -Beziehung. Wenn Eigenschaftsnamen identisch sind, sollten wir keine Mapping manuell bereitstellen müssen:
constructor TMyProfile.Create;
begin
// maps properties with same name in both classes
CreateMap<TDBUser,TUser>();
end ;
initialization
TAutoMapper.RegisterProfile<TMyProfile>;Wenn einige Eigenschaften einen unterschiedlichen Namen oder Typ haben, müssen wir benutzerdefinierte Zuordnungen verwenden:
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): Karten Sie einen Quelleigenschaftsnamen in einen Zieleigenschaftsnamen. IgnoreAllnonexisting: Ignorieren Sie alle nicht vorhandenen Eigenschaften am Ziel.
Ignoreothermembers: Nur Eigenschaften, die in benutzerdefinierter Zuordnung definiert sind, werden gelöst.
ResolveUnMapped: versucht, eine Karte ohne definierte Profilemap automatisch zu beheben.
Der Automapper -Service kann in ein Objekt/Controller injiziert werden, das die Abstraktion in Anwendungsklauseln definiert.
uses
Quick.Core.Mapping.Abstractions;
...
TMyController.Create(aMapper : IMapper);..und benutze es:
product := fMapper.Map(dbproduct).AsType<TProduct>;Möchten Sie Delphi lernen oder Ihre Fähigkeiten verbessern? Learndelphi.org