
Delphi Framework (Windows/Linux/Android/MacOSX/iOS) เพื่อสร้างเดสก์ท็อปที่มีประสิทธิภาพสูงและปรับขนาดได้บนมือถือและเว็บแอปพลิเคชันได้อย่างง่ายดาย Delphi 10 ถึง 12 เอเธนส์สนับสนุน
ได้โปรด "Star" โครงการนี้ใน GitHub! ไม่มีค่าใช้จ่ายใด ๆ นอกจากช่วยอ้างอิงรหัส 
หากคุณพบว่าโครงการนี้มีประโยชน์โปรดพิจารณาบริจาค
abstractions:
บริการ:
MVC:
ส่วนขยาย:
ส่วนขยาย MVC:
อัปเดต:
QuickCore เป็นเฟรมเวิร์กสำหรับสร้างเดสก์ท็อป/มือถือ/เว็บแอพ
เฟรมเวิร์กทั้งหมดขึ้นอยู่กับการฉีดพึ่งพาการฉีดพึ่งพา คอนเทนเนอร์ถือบริการทั้งหมดที่ต้องการโดยแอปพลิเคชันช่วยให้การเปลี่ยนแปลงโครงสร้างพื้นฐานง่ายขึ้นด้วย enfort เล็กน้อย
บริการจะถูกฉีดลงในเซิร์ฟเวอร์โดยอัตโนมัติและกำหนดค่าจากหน่วยเดียว "เริ่มต้น" ทุกโครงการหลักต้องการการเริ่มต้น PAS พร้อมคลาสที่สืบทอดมาจาก TStartupBase (ดูตัวอย่างในโฟลเดอร์ตัวอย่าง)
เป็นชุดของบริการที่เราสามารถลงทะเบียนบริการที่กำหนดไว้ล่วงหน้าหรือกำหนดเองและควบคุมวงจรชีวิต (Singleton, Transient, .. ) ServiceCollection เป็นคอนเทนเนอร์ Build-in ที่รวมอยู่ใน QuickCore และรองรับการฉีดคอนสตรัคเตอร์โดยค่าเริ่มต้น
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 ทำงานร่วมกับอินเทอร์เฟซ Ilogger เราสามารถใช้ส่วนขยายการบันทึกการสร้างหรือกำหนดการใช้งานของตัวเองและฉีด
หากต้องการใช้การใช้งาน QuickLogger (ต้องการไลบรารี Quicklogger ดูข้อกำหนดการติดตั้ง) Quicklogger ใช้ตัวสร้าง Ilogger เพื่อการกำหนดค่าที่ง่าย ตัวเลือกเริ่มต้นสามารถส่งผ่านเป็นฟังก์ชันตัวเลือกที่ได้รับมอบหมาย เมื่อไฟล์ config QuickLogger มีอยู่จะไม่มีตัวเลือกเริ่มต้นเพิ่มเติมเพิ่มเติม:
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
);... หรือเพิ่มการใช้งาน Logger ของตัวเอง
services.AddLogging(MyLogger);ไฟล์กำหนดค่าการบันทึกข้อมูลการบันทึก QuickCore ถูกบันทึกเป็นไฟล์ quicklogger.yml o json การใช้ตัวแปรสภาพแวดล้อม core_environment เราสามารถกำหนดไฟล์ที่ใช้สำหรับการใช้งานแต่ละครั้ง หากมีการกำหนดตัวแปรสภาพแวดล้อม QuickCore จะพยายามโหลด/บันทึก "QuickCore [core_environment] .yaml/json"
QuickCore ทำงานร่วมกับรูปแบบตัวเลือก วัตถุ Toptions ทุกชิ้นจะถูกบันทึกเป็นส่วนในไฟล์ config และสามารถฉีดลงในบริการหรือตัวควบคุมคอนโทรลเลอร์ บริการตัวเลือกจำเป็นต้องเพิ่มไปยัง ServiceCollection ก่อนที่เราจะสามารถเพิ่มส่วนต่างๆได้ เราสามารถกำหนดชื่อไฟล์ config และรูปแบบ JSON หรือ YAML
.AddOptions(TOptionsFileFormat.ofYAML,True)ทุกส่วนการกำหนดค่าจะต้องเพิ่มและสามารถกำหนดค่าด้วยค่าเริ่มต้น
services.Configure<TAppSettings>(procedure(aOptions : TAppSettings)
begin
aOptions.Smtp := ' mail.domain.com ' ;
aOptions.Email := ' [email protected] ' ;
end )
และเราสามารถฉีดมันได้ในภายหลังง่ายเหมือน ...
constructor TMyController.Create(aLogger : ILogger; aAppSettings : IOptions<TAppSettings>);
begin
fOptions := aAppSettings. Value ;
fSMTPServer.Host := fOptions.Smtp;
end ;เข้าสู่การกำหนดค่าเริ่มต้นคุณสามารถใช้ตัวเลือกการอ่านเพื่อดำเนินการเสริม:
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 ;การใช้ตัวแปรสภาพแวดล้อม core_environment เราสามารถกำหนดไฟล์ที่ใช้สำหรับทุกการใช้งาน หากมีการกำหนดตัวแปรสภาพแวดล้อม QuickCore จะพยายามโหลด/บันทึก "QuickCore [core_environment] .yaml" ไฟล์
หากไม่ได้กำหนดตัวเลือก NAME ชื่อคลาสจะถูกใช้เป็นชื่อส่วนในไฟล์กำหนดค่า ทุกตัวเลือกที่กำหนดค่าจะถูกบันทึกและโหลดไปยังไฟล์กำหนดค่า แต่ถ้าเราต้องการเราสามารถซ่อนตัวเลือกบางอย่างจากได้รับการบันทึก ใช้ตัวเลือก hideoptions: = true (สำหรับตัวเลือกภายในไม่สามารถกำหนดค่าได้จากภายนอก)
Debugger เป็นตัวติดตาม Debugger ที่เรียบง่าย (ดูเอกสาร QuickLib) ในการเชื่อมต่อดีบักเกอร์ด้วยบริการการบันทึกจะต้องเพิ่มบริการดีบั๊กใน ServiceCollection (โดยค่าเริ่มต้นใช้เอาต์พุตคอนโซล):
services.AddDebugger;การทำงานกับพารามิเตอร์ CommandLine จะง่ายโดยใช้ส่วนขยาย CommandLine กำหนดคลาสที่สืบทอดมาจาก tparameters หรือ tserviceParameters (หากทำงานกับ QuickAppServices) พร้อมอาร์กิวเมนต์ที่เป็นไปได้ของคุณ:
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 ;และส่งผ่านไปยังส่วนขยาย DE Commandline:
services.AddCommandline<TArguments>;เมื่อคุณโทรหา exe ของคุณด้วย -ช่วยเหลือคุณจะได้รับเอกสาร หากคุณต้องการตรวจสอบสวิตช์หรือค่าคุณสามารถทำได้เช่นนี้:
if services.Commandline<TArguments>.Port = 0 then ...
if services.Commandline<TArguments>.Silent then ...สามารถเพิ่มอินเทอร์เฟซและการใช้งานใน serviceCollection Addsingleton และ AddTransient อนุญาตให้กำหนดวัฏจักรสด
services.AddSingleton<IMyService,TMyService>;หรือด้วยการสร้างที่ได้รับมอบหมาย
services.AddTransient<IMyService,TMyService>(function : TMyService)
begin
Result := TMyService.Create(myparam);
Result.Host := ' localhost ' ;
end );หรือเพิ่มการใช้งาน
services.AddSingleton<TMyService>;ส่วนขยายเป็นบริการที่ฉีดได้เราสามารถเพิ่มลงในแอพ/เซิร์ฟเวอร์ของเรา ส่วนขยายจะถูกฉีดเข้าไปในหน่วยเริ่มต้น ServiceCollection การขยายวิธีการ ServiceCollection ทำงานคล้ายกับ. NET Extension Method
ในการเพิ่มส่วนขยายเราจำเป็นต้องเพิ่มหน่วยลงในหน่วยเริ่มต้นใช้ประโยค (ดูส่วนขยายที่กำหนดไว้ล่วงหน้าของ QuickCore ด้านบน)
uses
Quick.Core.Extensions.AutoMapper;
...
begin
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;
end ;ด้วย QuickCore เราสามารถสร้างเว็บแอปพลิเคชันด้วยคอนโทรลเลอร์และการกระทำ
สร้างแอปพลิเคชันเซิร์ฟเวอร์และกำหนดการเชื่อมโยงและความปลอดภัย
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): อนุญาตให้เพิ่มคอนโทรลเลอร์ลงในเว็บแอปเซิร์ฟเวอร์
AddControllers: เพิ่มตัวควบคุมทั้งหมดที่ลงทะเบียนในระหว่างหน่วยการเริ่มต้นด้วย RegisterController (ControlLerClass);
USEWEBROOT (PATH): กำหนดไฟล์/โฟลเดอร์ข้อมูลคงที่
USECUSTOMERRORPAGES: เปิดใช้งานการใช้หน้าข้อผิดพลาดที่กำหนดเอง ในข้อผิดพลาด 403 เซิร์ฟเวอร์จะค้นหาไฟล์ 403.HTML, 40x.html หรือ 4xx.html หากระบุหน้า Dinamic รูปแบบหนวดที่เรียบง่ายจะถูกแทนที่ด้วยข้อมูลข้อผิดพลาด (statuscode, statusmsg ฯลฯ )
USEMUSTACHEPAGES: เอ็นจิ้นเทมเพลตหนวดง่าย ๆ เพื่อแทนที่มุมมองที่เรียบง่าย
Middlewares เป็นเหมือนเลเยอร์ของฟังก์ชันการทำงานและวิ่งเข้าไปในท่อส่งคำขอ ทุกคำขอผ่านสำหรับแต่ละ middlwares (ตามลำดับการสร้าง) หรือไม่ขึ้นอยู่กับ requeriments middelware
USESTATICFILES: เพื่อให้บริการเนื้อหาคงที่
USEHSTS: มิดเดิลแวร์ความปลอดภัยการขนส่งที่เข้มงวดของ HTTP เพื่ออนุญาตการเชื่อมต่อ HTTPS เท่านั้น
USEHTTTPREDIRECTION: เปิดใช้งานมิดเดิลแวร์การเปลี่ยนเส้นทางเพื่อเปลี่ยนเส้นทางตามตำแหน่งส่วนหัวที่พบ
Userouting: เปิดใช้งานการกำหนดเส้นทางมิดเดิลแวร์เพื่อรับเส้นทางการจับคู่จากคำขอ
USEMVC: เปิดใช้งาน MVC Middleware เพื่อจัดการและเปลี่ยนเส้นทางทุกคำขอไปยังการกระทำหรือมุมมองคอนโทรลเลอร์ผู้สื่อข่าว
usemiddleware: เพื่อเพิ่มคลาสมิดเดิลแวร์ที่กำหนดเองเพื่อขอไปป์ไลน์
ใช้ (RequestDelegate): ดำเนินการวิธีการไม่ระบุชื่อเป็นมิดเดิลแวร์
USEAUTHENTICATION: พยายามรับข้อมูลการรับรองความถูกต้องจากคำขอ
Useauthorization: อนุญาต/ไม่อนุญาตให้ใช้ทรัพยากรตามนโยบายการอนุญาต
คอนโทรลเลอร์ทุกตัวมีอยู่ใน thttpcontroller และวิธีการที่เผยแพร่กลายเป็นการกระทำ ด้วยแอตทริบิวต์ที่กำหนดเองเราสามารถกำหนดเส้นทางการอนุญาต ฯลฯ ของวิธีการเหล่านี้ เนื่องจากคอนโทรลเลอร์ทั้งหมดถูกฉีดจากการฉีดขึ้นอยู่กับการพึ่งพาเราสามารถกำหนดตัวสร้างด้วยพารามิเตอร์ autoinjectable และ IOC จะพยายามแก้ไขการสร้างตัวสร้าง
constructor THomeController.Create(aLogger: ILogger);การกำหนดเส้นทาง HTTP เป็นแอตทริบิวต์ที่กำหนดเอง เราจำเป็นต้องกำหนดเส้นทางสำหรับคอนโทรลเลอร์แต่ละตัวและวิธีการ/การกระทำ
[HttpGet( ' home/index ' )]
function THomeController.Index : IActionResult;
[HttpPost( ' home/GetAll ' )]
function THomeController.GetAll : IActionResult;หากการกำหนดเส้นทางที่กำหนดไว้ในชั้นเรียนจะเป็นทั่วโลกและไม่จำเป็นต้องทำซ้ำในแต่ละวิธี/การกระทำ:
[Route( ' home/other ' )]
THomeController = class (THttpController)
published
[HttpPost( ' GetAll ' )] // global + local = home/other/GetAll
function THomeController.GetAll : IActionResult;พารามิเตอร์ถูกกำหนดด้วยแอตทริบิวต์และแยกวิเคราะห์และฉีดเป็นพารามิเตอร์วิธีการโดยอัตโนมัติ
[HttpGet( ' Add/{productname}/{price} ' )]
function Add ( const ProductName : string; Price : Integer): IActionResult;พารามิเตอร์สามารถพิมพ์ได้ int: ตัวเลขอัลฟ่าเท่านั้น: ตัวอักษรเท่านั้น ลอย: มีเพียงตัวเลขลอยตัว
[HttpGet( ' Add/{productname:alpha}/{price:float} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;หนึ่ง ? กำหนดพารามิเตอร์เป็นตัวเลือก
[HttpGet( ' Add/{productname:alpha}/{price:float?} ' )]
function Add ( const ProductName : string; Price : Extended): IActionResult;เพื่อรับพารามิเตอร์จากตัวถังคำขอ (พร้อม deserialization อัตโนมัติ)
[HttpPost( ' Add/User ' )]
function Add ([FromBody] User : TUser): IActionResult;ผลการดำเนินการเป็นผลลัพธ์ของคอนโทรลเลอร์ StatusCode (StatusCode, Statustext): ส่งคืนรหัสสถานะและข้อความสถานะทางเลือกไปยังไคลเอนต์
Result := StatusCode( 200 , ' ok ' );ตกลง (Statustext): ส่งคืนรหัสสถานะ 200 และ Statustext เสริม
ยอมรับ (Statustext): ส่งคืนรหัสสถานะ 202 และข้อความสถานะทางเลือก
Badrequest (Statustext): ส่งคืนรหัสสถานะ 400 และข้อความสถานะทางเลือก
Notfound (Statustext): ส่งคืนรหัสสถานะ 404 และข้อความสถานะทางเลือก
Forbid (Statustext): ส่งคืนรหัสสถานะ 403 และข้อความสถานะทางเลือก
ไม่ได้รับอนุญาต (Statustext): ส่งคืนรหัสสถานะ 401 และข้อความสถานะทางเลือก
การเปลี่ยนเส้นทาง (URL): ส่งคืนการเปลี่ยนเส้นทางชั่วคราวไปยัง URL
RedirectPermament (URL): ส่งคืนการเปลี่ยนเส้นทางถาวรไปยัง URL
เนื้อหา (ข้อความ): ส่งคืนข้อความตอบกลับ
JSON (Object, OnlyPublishedProperties): ส่งคืนวัตถุหรือรายการ JSON ที่เป็นอนุกรม หากเปิดใช้งานเฉพาะ PublishedProperties จะมีเพียงคุณสมบัติที่เผยแพร่โดยวัตถุเท่านั้น
Result := Json(User);View (ViewName): ส่งคืนมุมมอง
Result := View ( ' home ' );Extension Automapper อนุญาตให้ MAP ประเภทคลาสไปยังประเภทคลาสอื่น ในการใช้ Automapper เราต้องเพิ่มบริการลงใน ServiceCollection ใน Statup Unit:
services.Extension<TAutoMapperServiceExtension>
.AddAutoMapper;จากนั้นกำหนดแผนที่โปรไฟล์ด้วยความสัมพันธ์การทำแผนที่ หากชื่อทรัพย์สินเหมือนกันเราไม่ควรจัดทำแผนที่ด้วยตนเอง:
constructor TMyProfile.Create;
begin
// maps properties with same name in both classes
CreateMap<TDBUser,TUser>();
end ;
initialization
TAutoMapper.RegisterProfile<TMyProfile>;หากคุณสมบัติบางอย่างมีชื่อหรือประเภทที่แตกต่างกันเราต้องใช้การแมปแบบกำหนดเอง:
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): แผนที่ชื่อคุณสมบัติต้นฉบับไปยังชื่อคุณสมบัติเป้าหมาย ไม่รู้ว่า: เพิกเฉยต่อคุณสมบัติที่ไม่มีอยู่ทั้งหมดในเป้าหมาย
เพิกเฉยต่อสมาชิก: คุณสมบัติเฉพาะที่กำหนดไว้ในการแมปแบบกำหนดเองเท่านั้นที่จะได้รับการแก้ไข
ResolveunMapped: พยายามแก้ไขแผนที่ใด ๆ โดยอัตโนมัติโดยไม่ต้องกำหนด profileMap
บริการ Automapper สามารถฉีดเข้าไปในวัตถุ/คอนโทรลเลอร์ที่กำหนดสิ่งที่เป็นนามธรรมในส่วนการใช้งาน
uses
Quick.Core.Mapping.Abstractions;
...
TMyController.Create(aMapper : IMapper);.. และใช้:
product := fMapper.Map(dbproduct).AsType<TProduct>;คุณต้องการเรียนรู้ Delphi หรือพัฒนาทักษะของคุณหรือไม่? LearnDelphi.org