ประวัติการอัพเดต: หมายเลข 1
เวลาอัปเดต: 01-11-2544 20:09 น
อัปเดตโดย: Musicwind®
หมายเหตุการอัปเดต: ร่างแรกเสร็จสมบูรณ์
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~~
สรุป:
บทความนี้อธิบายวิธีการ ส่งออกคลาสใน Dll - คลาสย่อยจำนวนมากตามคลาสนามธรรมเฉพาะ เทคโนโลยีนี้ใช้แนวคิดเรื่องความหลากหลายทำให้เราได้รับเอฟเฟกต์ที่คล้ายกับปลั๊กอิน
ผู้อ่านที่ต้องการ:
เข้าใจแนวคิดของความหลากหลาย เข้าใจแนวคิดของเมตาคลาส
ความยากทางเทคนิค:
6/10 .
ในการส่งออกคลาสจาก Dll สิ่งแรกที่คุณต้องนึกถึงคือการใช้แพ็คเกจ bpl ข้อเสียประการหนึ่งของวิธีนี้คือผู้ใช้ต้องรู้ว่าคลาสใดอยู่ในแพ็คเกจ ซึ่งหมายความว่าต้องทราบชื่อของคลาส - นี่เป็นข้อจำกัดในแง่หนึ่ง ลองนึกภาพสถานการณ์ที่ผู้ใช้กำหนดชั้นล่างสุด คลาสนามธรรม และคลาสแอปพลิเคชันมากมาย (concrete class) จากนั้นสำหรับผู้ใช้ เขาหวังว่าจะสามารถใช้คลาสเหล่านี้ได้โดยไม่ต้องรู้คลาสเฉพาะ - ดูเหมือนจะลึกลับเล็กน้อยที่จะพูดแบบนี้ แต่สถานการณ์จริงเป็นเช่นนั้นจริง ๆ เนื่องจากไม่สามารถคาดเดาได้เมื่อกำหนดนามธรรม ในอนาคตจะมีคลาสเฉพาะจำนวนกี่คลาส แล้วจะต้องใช้เทคโนโลยีประเภทใดในการตระหนักถึงความต้องการดังกล่าว
ในความเป็นจริงความยากทางเทคนิคในการดำเนินการนั้นไม่ใช่เรื่องยากมากนัก - ผู้เขียนที่นี่อุทิศประสบการณ์เชิงปฏิบัติให้กับทุกคนเพื่อดึงดูดแนวคิดใหม่ ๆ และหวังว่าจะเห็นวิธีการอื่นที่ดีกว่า!
ขั้นแรกต่อไปนี้จะแนะนำความรู้พื้นฐานบางอย่างที่เกี่ยวข้องกับวิธีนี้ จากนั้นใช้ตัวอย่างเพื่อแสดงการใช้งานเฉพาะ
1. แนวคิดพื้นฐาน
คลาส Meta (คลาสเมตา) หรือที่เรียกว่าประเภทการอ้างอิงคลาส (ประเภทการอ้างอิงคลาส) ถือได้ว่าเป็นประเภทของคลาส และค่าของตัวแปรที่ประกาศด้วยประเภทนี้แสดงถึงคลาส ตัวอย่างเช่น:
พิมพ์
TClass = คลาสของ TObject;
นี่เป็นการประกาศประเภท metaclass จากนั้นคุณสามารถมีการประกาศตัวแปรได้ดังนี้:
วาร์
คลาส: TClass;
จากนั้นคุณสามารถใช้มันได้ดังนี้:
AClass := TObject;
หรือ:
AClass := TButton;
หรือ:
AClass := TForm;
ฯลฯ
เนื่องจาก TClass เป็นเมตาคลาสประเภท TObject และ TButton, TForm ฯลฯ ล้วนมาจาก TObject ค่าต่างๆ เช่น TButton และ TForm จึงเป็นที่ยอมรับของ AClass
จากนั้นเราสามารถใช้แนวคิดเรื่องความหลากหลายและใช้ตัวแปรคลาส AClass ได้อย่างยืดหยุ่น นี่เป็นความรู้พื้นฐานสำหรับการดำเนินการเฉพาะด้านล่างนี้ด้วย
2. การนำไปปฏิบัติโดยเฉพาะ
ขั้นตอนแรกคือการสร้างคลาสนามธรรม:
เราใช้การประกาศธรรมดา ๆ คลาสนามธรรมมีเพียงวิธีนามธรรมเท่านั้น แต่มันไม่ส่งผลกระทบต่อคำอธิบายปัญหาของเรา:
TMyBaseForm = คลาส (TForm)
ป้องกันแล้ว
ฟังก์ชั่น GetTitle: pchar เสมือน;
จบ;
MyBaseFormClass = คลาสของ TMyBaseForm;
อย่ามาคุยกันว่าคลาสนามธรรมมีวิธีการและอินเทอร์เฟซในทางปฏิบัติมากมายเพียงใด เพราะสิ่งที่เราต้องการจะพูดถึงคือความเป็นไปได้ทางเทคนิค สมมติว่าความตั้งใจดั้งเดิมของผู้เขียนในการกำหนดอินเทอร์เฟซนี้คือการขอรับ Titles ที่เปลี่ยนแปลงจำนวนเท่าใดก็ได้ และค่าที่ส่งคืนเฉพาะของ GetTitle จำเป็นต้องถูกนำไปใช้โดยคลาสย่อย นอกจากนี้ผู้เขียนยังหวังว่าโค้ดของคลาสย่อยสามารถนำไปใช้ใน Dll และแยกออกจากโปรแกรมหลักได้ - วิธีนี้มีรสชาติแบบปลั๊กอินและอาจยังสามารถตระหนักถึงคุณสมบัติบางอย่างของ Plug&Play ได้ด้วยใช่ไหม มีเสน่ห์? แล้วคุณควรทำอย่างไรต่อไป?
ขั้นแรก โปรแกรมหลักและโปรแกรม Dll ควรรวมหน่วยที่ประกาศไว้ข้างต้น จากนั้น โปรแกรมหลักจะรับผิดชอบในการใช้งานไดรเวอร์ - โหลด Dll แบบไดนามิกและโหลดคลาสแบบไดนามิก และ Dll มีหน้าที่รับผิดชอบในการใช้งานคลาสย่อย
เรามาพูดถึง Dll กันก่อนว่า Dll ควรทำอย่างไร?
ขั้นตอนที่สองคือ การส่งออกคลาสย่อยใน Dll :
เราได้ออกแบบฟังก์ชันที่ส่งออกสองฟังก์ชันต่อไปนี้:
1. ฟังก์ชั่น GetClassCount: จำนวนเต็ม;
บอกผู้โทรว่ามีหลายคลาสย่อยใน Dll นี้
2. ฟังก์ชั่น GetClassTypeByIndex (const iIndex: จำนวนเต็ม;
var ClassType: MyBaseFormClass): WordBool;
รับคลาสย่อยเฉพาะตามดัชนี โปรดทราบว่าประเภทของ ClassType ที่นี่คือ MyBaseFormClass ซึ่งระบุว่าค่าของมันจะเป็นคลาสที่แน่นอนที่สืบทอดมาจาก TMyBaseForm
นี่คือการดำเนินการที่เป็นไปได้ประการหนึ่ง:
ฟังก์ชัน GetClassCount: จำนวนเต็ม;
เริ่ม
ผลลัพธ์ := 3; // ระบุว่ามีการส่งออก 3 คลาสใน Dll นี้
จบ;
ฟังก์ชั่น GetClassTypeByIndex (const iIndex: จำนวนเต็ม;
var ClassType: MyBaseFormClass): WordBool;
เริ่ม
ผลลัพธ์ := จริง;
กรณี iIndex ของ
0: ประเภทคลาส := TFrmTest1;
1: ประเภทคลาส := TFrmTest2;
2: ประเภทคลาส := TFrmTest3;
อื่น
ผลลัพธ์ := เท็จ;
จบ;
จบ;
แน่นอนว่าหน่วยที่มี TFrmTest1, TFrmTest2 และ TFrmTest3 ควรรวมอยู่ในรายการการใช้งานของหน่วย การใช้งาน TFrmTest1 อาจเป็นดังนี้:
TFrmTest1 = คลาส (TMyBaseForm)
ได้รับการคุ้มครอง
ฟังก์ชั่น GetTitle: PChar แทนที่;
จบ;
ฟังก์ชัน TFrmTest1.GetTitle: Pchar;
เริ่ม
ผลลัพธ์ := 'สวัสดีจาก TFrmTest1';
จบ;
สุดท้ายอย่าลืมเพิ่ม GetClassCount และ GetClassByIndex ลงในรายการส่งออก จากนั้น เมื่อสร้างโครงการ Dll โปรดทำเครื่องหมายที่ "ใช้แพ็คเกจรันไทม์" ในแพ็คเกจตัวเลือกโครงการ เหตุผลเฉพาะจะมีการหารือในภายหลัง
ณ จุดนี้ งานบน Dll ได้สิ้นสุดลงแล้ว
ขั้นตอนที่สามคือการใช้งานเอ็นจิ้นไดรเวอร์โปรแกรมหลัก:
ขั้นตอนนี้ค่อนข้างง่าย - ไม่มีอะไรมากไปกว่าการโหลด Dll แบบไดนามิก จากนั้นเรียกใช้ฟังก์ชัน GetClassCount จากนั้นเรียกใช้ GetClassByIndex รหัสกุญแจ:
วาร์ AClass: TMyBaseClass;
แบบฟอร์ม: TMyBaseForm;
ฉัน iCount: จำนวนเต็ม;
blResult: บูลีน;
เริ่ม
//ละเว้นส่วนที่เกี่ยวกับการโหลดไลบรารีแบบไดนามิก โดยสมมติว่า FPGetClassProc ชี้ไปที่ฟังก์ชัน GetClassCount และ FPGetClassByIndexProc ชี้ไปที่ GetClassByIndex จากนั้น:
iCount := FPGetClassProc;
สำหรับฉัน := 0 ถึง iCount ?C 1 ทำ
เริ่ม
AClass := FPGetClassByIndex(I, blResult);
ถ้า blResult แล้ว
เริ่ม
AForm := AClass.Create (แอปพลิเคชัน);
AForm.Caption := AForm.GetTitle;
AForm.Show;
จบ;
จบ;
-
จบ;
โปรดทราบว่าเช่นเดียวกับ Dll คุณต้องเลือกใช้แพ็คเกจรันไทม์เมื่อสร้างไฟล์เอาต์พุต เนื่องจากการไม่ใช้แพ็คเกจรันไทม์จะส่งผลให้มีสำเนาของคลาสเดียวกันหลายชุดในหน่วยความจำ ดังนั้นการใช้ตัวดำเนินการ Is จะส่งกลับผลลัพธ์ที่เป็นเท็จ
Musicwind®@HangZhou.Zhejiang.China
01-11-2544
บทความเพิ่มเติม
[ ท้ายบทความ]