PracticU

Reflection - חלק 2

בלי כתוביותעם כתוביות
PracticU › קורס תכנות מתקדם - #Advanced .NET C › Reflection - חלק 2
מילון מושגים:
DLL - קובץ ספרייה ב-Windows המכיל קוד ופונקציות שתוכנות שונות יכולות לטעון ולהשתמש בהן במשותף.
מערך - מבנה נתונים שמאחסן אוסף ערכים מאותו סוג ברצף, שאפשר לגשת אליהם לפי מספר מיקום (אינדקס).
בנאי - מתודה מיוחדת שמופעלת אוטומטית בעת יצירת אובייקט ממחלקה, ומאתחלת את ערכיו ההתחלתיים.
מחרוזת - סוג נתונים שמייצג רצף של תווים, כלומר טקסט, ומשמש לאחסון מילים, משפטים או כל רצף סימנים.
קומפיילר - תוכנה שממירה קוד מקור שנכתב בשפת תכנות לקוד שהמחשב יכול להריץ, ומדווחת על שגיאות תחביר.
מחלקה - תבנית בתכנות מונחה עצמים שמגדירה אילו נתונים ופעולות יהיו לאובייקטים שנוצרים ממנה.
אינדקס - מבנה במסד נתונים שמאיץ חיפוש ושליפה. גם מספר המציין מיקום של איבר במערך.
פרמטר - ערך שמועבר לפונקציה או לפקודה כקלט, ומשפיע על אופן פעולתן ועל התוצאה שהן מחזירות.

Reflection - חלק 2
השיעור ממשיך את נושא ה-Reflection ועובר מהטיפוס עצמו אל החברים שבתוכו: שדות, תכונות, בנאים ושיטות. בסוף מראים כיצד יוצרים אובייקט מ-DLL שלא הכרנו בזמן הפיתוח.
חברי הטיפוס
1. שדות: GetFields מחזיר מערך של FieldInfo לכל השדות. כברירת מחדל לא מוחזרים שדות פרטיים, ולכן השדה age לא הופיע בהדגמה הראשונה.
2. תכונות: GetProperties מחזיר את התכונות. בהדגמה הופיעה רק התכונה age, כי היא היחידה שחשופה.
3. בנאים: GetConstructors מחזיר את הבנאים. בהדגמה הופיעו שני בנאים: בנאי ריק ובנאי עם שני מחרוזות ומספר.
4. שיטות: GetMethods מחזיר את כל השיטות, כולל אלה שהגיעו מהטיפוס Object: ToString, Equals, GetHashCode ו-GetType. תכונה מומרת על ידי הקומפיילר לשתי שיטות, get ו-set, וזה מופיע בתוצאה.
5. הכול יחד: GetMembers מחזיר את כל החברים בבת אחת.
6. BindingFlags: דגלים שמגדירים אילו חברים לחפש. למשל NonPublic לחברים פרטיים, Instance לחברים של אובייקט ו-Static לחברים סטטיים.
שימוש דינמי ב-DLL
7. מצב התרחיש: התוכנית מקבלת DLL בזמן הריצה ואינה מכירה את המחלקות בזמן הפיתוח. צריך לדעת את שם ה-Assembly, שם הטיפוס ושמות החברים מקובץ הגדרה חיצוני.
8. יצירת אובייקט: Activator.CreateInstance מקבל את שם ה-Assembly ואת שם הטיפוס. התוצאה היא ObjectHandle, ו-Unwrap מחזיר את האובייקט עצמו.
9. שדה ותכונה: SetValue על FieldInfo או PropertyInfo דורש לציין את האובייקט שאליו מכניסים את הערך. ל-PropertyInfo של אינדקסר מעבירים null במקום אינדקס.
10. שיטה: Invoke על MethodInfo מקבל את האובייקט ואת רשימת הפרמטרים.
11. גישה לשדה פרטי: בעזרת BindingFlags אפשר להגיע לשדה פרטי ולכתוב בו ערך, גם בעקיפת התכונה שמגינה עליו. בדרך כלל זה לא רצוי, כי זה שובר את ההכמסה של האובייקט.
Reflection מאפשר לעבוד עם טיפוס גם כשאינו ידוע בזמן הקומפילציה, אבל כל שימוש בו מוותר על בדיקת הטיפוסים של הקומפיילר.
השיעור הבא בקורס: תרגילים על Reflection

פרקי ההרצאה: Reflection - חלק 2

  1. 00:00

    בניית מחלקת Person עם Fields ו-Properties

  2. 03:10

    קריאת Fields עם GetField ו-GetFields

  3. 05:08

    קריאת Properties עם GetProperties

  4. 06:13

    קבלת Constructors עם GetConstructors

  5. 07:32

    קריאת Methods עם GetMethods

  6. 09:09

    קבלת כל ה-Members עם GetMembers

  7. 11:45

    טעינה דינמית של DLL עם Reflection

  8. 14:15

    בניית Class Library כ-DLL

תמלול ההרצאה: Reflection - חלק 2

הטקסט המלא של הדקות הראשונות בהרצאה «Reflection - חלק 2» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:03

    אוקיי, קודם כל יש לנו כאן טייפ ואנחנו רוצים טייפ לגבי פרסון. בואו נלך ונבנה פה את קלאס פרסון ובקלאס פרסון נגדיר את הדברים הבאים public string first name last name private int underline age public int age עם a גדולה שהולך להיות פרופרטי

  2. 00:47

    יש לפרופרטי הזה את חלק הגט שמחזיר את underline age ויש לפורפרטי הזה את חלק ה-set, מבצע בדיקה. האם ה-value שאנחנו מנסים להכניס אכן הוא חוקי?

  3. 01:08

    האם הוא גדול שווה לאפס? ורק אם הוא חוקי, אנחנו מכניסים אותו ל-underline h. יש לנו כאן קונסטרקטור דרק, קונסטרקטור שמקבל את שלושת ה-data members, first name, last name, h, ומבצע השמה שלהם.

  4. 01:35

    first name מקבל את ה-first name, אהלן last name ו-age חייב לעבור דרך ה-property בכדי לבצע את הבדיקה. בנוסף יש לנו כאן פונקציה שמציגה את הפרטים, נציג first name, נציג last name, נשנה פה את ההדפסה ונציג את ה-age וכעת בנינו את המחלקה person שיש לה גם data members,

  5. 02:24

    גם property, גם קונסטרקטורים וגם מתודות. אוקיי, איך זה נקרא? DataMember נקרא Field, מאפיין נקרא Property.

  6. 02:49

    כל הקונסטרקטורים נקראים קונסטרקטורס, ומתודה זה Method. כל אלה מונחים של Object Oriented שאנחנו כבר מכירים.

  7. 03:00

    אבל בכוונה הגדרתי אותם שוב, כי אנחנו הולכים עכשיו לקרוא את ערכם. אז יש לנו פה את הטייפ P, ועכשיו אנחנו יכולים לגשת ל-T נקודה ועל ידי פונקציות ה-Get לקבל את כל מה שאנחנו רוצים בעצם.

  8. 03:20

    לדוגמה בואו נתחיל עם ה-Fields. אנחנו יכולים לקבל נתונים לגבי פילד בודד, כמובן אנחנו צריכים לתת את ה-שם שלו, פה אנחנו רואים שנתנו את ה-Name, אנחנו צריכים לקבל את ה-Name, לשלוח את ה-Name ליתר דיוק, או GetFields נותן לנו נתונים לגבי כל ה-Fields.

  9. 03:40

    GetFields מחזיר אובייקט מסוג FieldInfo, אינפורמציה לגבי פילד בודד, כאשר פילד כאמור זה DataMember, כלומר משתנה ברמת מחלקה. getField מחזיר לנו אותו הדבר אבל מערך חד-ממדי fieldInfo סוגריים מרובעים בואו נקרא את כל ה-fields אז כל מה שאנחנו צריכים לעשות זה לקרוא ל-getFields

  10. 04:09

    לקבל fieldInfo שימו לב שזה נמצא במרחב השמות System Reflection זה כאמור מערך חד-ממדי ואנחנו יכולים לגשת ולבצע הדפסה של כל ה-fields נרוץ ב-foreach, field info, in fields ופשוט נציג את הפריט עצמו ונראה מה מוצג כאשר אנחנו מריצים את התוכנית.

  11. 04:49

    אז אנחנו רואים שיש לנו כרגע רק את ה-first name ואת ה-last name. איפה ה-age? הרי קיים לנו data member שנקרא age, זה בהחלט field, אז by default לא חוזרים לנו ערכים שהם private.

  12. 05:07

    ואנחנו יכולים להתגבר על הסיטואציה הזאת וגם לראות ערכים שהם פרייבט אנחנו נתעסק עם זה עוד מעט. אבל מה בקשר לדברים נוספים? אלה היו ה-Fields.

  13. 05:20

    מה בקשר ל-Properties? יש לנו PropertyInfo. ניקח את כל ה-Properties, t.getProperties. גם כאן ראינו יש לנו אפשרות להשיג את כל ה-Properties או Property אחד ספציפי.

  14. 05:44

    בואו ניגש ונביא את כל ה-Properties, נציג את רשימת ה-Properties, רופרטי אינפו נרוץ על הפרופרטיז ואנחנו מציגים את הפרופרטיז עצמם, בואו נריץ ונראה שיש לנו רק פרופרטי אחד ויחיד שנקרא age והוא מחזיר לנו אינטג'ר שזה int32. קונסטרקטורים זה הדבר הבא בתור שיש לנו, קונסטרקטור אינפו מתאר לנו את הקונסטרקטורים וניחשתם נכון get

  15. 06:35

    קונסטרקטור בודד או קונסטרקטורי בואו נקבל את כל הקונסטרקטורים שיש לנו נציג את כל הקונסטרקטורים for each constructor info in constructors נריץ את זה ויש לנו כעת שני קונסטרקטורים שאנחנו רואים שהם קיימים אחלה קונסטרקטור אחד ריק קונסטרקטור אחד שמקבל סטרינג סטרינג ואינט מתודות method info או get method אחת ויחידה או get methods בואו

  16. 07:37

    נקרא ל get methods נרוץ על כל המתודות ושימו לב שיש לנו הרבה יותר מתודות ממה שקיימות במחלקה פרסון.

  17. 08:04

    אז למה יש לנו כל כך הרבה מתודות? בואו נסתכל רגע על המחלקה פרסון עצמה, ונראה שבמחלקה פרסון קיימת לנו מתודה אחת ויחידה שנקראת פרינט.

  18. 08:13

    אם אנחנו נריץ את זה, אנחנו הולכים לראות שיש לנו איזושהי מתודה שנקראת get_h ומתודה שנקראת set_h. אלו כאמור מתודות שמייצגות את ה-property h.

  19. 08:30

    יודעים שproperty מוחלף על ידי הקומפיילר לשתי מתודות get וset והנה אנחנו רואים אותם כאן. זאת אומרת מה שקיים בעצם באמת בפועל בתוך קוד ה-NSI-L זה ה-get וה-set האלה כמתודות.

  20. 08:47

    אוקיי, הנה הפרינט שלנו אבל מהם ארבעת הפונקציות שאנחנו רואים כאן? אז אלה פונקציות שהגיעו כמובן מהמחלקה שירשנו.

  21. 08:58

    אנחנו ירשנו את Object ולכן יש לנו פה את 2String, Equals, GetHashCode ו-GetType. ארבעת אלה הגיעו אלינו מ-Object ולכן אנחנו רואים אותם בסדרת הפונקציות ששייכות ל-Person.

  22. 09:14

    הדבר הבא שאנחנו יכולים להשיג זה משהו שנקרא MemberInfo. כאן, שוב פעם יש לנו מרמר בודד או GetAllMembers. אז מה זה?

  23. 09:31

    Member. Member זה כל דבר שנמצא בתוך Person. זה יהיה Fields, Properties, Constructors, Methods וכולי. בואו נרוץ ב-For each, Member info, נציג רק לפני שאנחנו הולכים לצפות בכל ה-Members, נריץ ונראה שעכשיו אנחנו רואים גם את הפונקציות,

  24. 10:07

    גם את ה... עד לכאן זה הפונקציות, יש לנו פה את ה-Setors, יש לנו פה את ה-Property והנה יש לנו פה את ה-Fields, הכל ביחד כאשר אנחנו קוראים עם Get Members.

  25. 10:19

    שימו לב שגם כאן לא קיבלנו ערכים שהם פרייבט, אנחנו כמובן הולכים לטפל בזה בהמשך. אז בדוגמה הזאת ראינו איך אנחנו יכולים לקרוא מידע לא רק של המחלקה פרסון, אלא גם דברים שנמצאים בתוך המחלקה פרסון.

  26. 10:37

    אז בדוגמה הקודמת ובדוגמה הזאת קראנו נתונים ורק הצגנו אותם. אם אנחנו רוצים במהלך הריצה לחקור את המידע ולראות מה יש בתוך טיפוס מסוים, ככה אנחנו עושים את זה.

  27. 10:52

    בואו נראה או נחשוב על איזושהי דוגמה שנרצה לעשות את הדבר הזה. יכולת מצב שאנחנו מקבלים איזשהו אובייקט ואנחנו רוצים לקרוא אותו ולפי המידע שיש בו לגשת לדאטאבס לטבלה מסוימת או ליתר דיוק לפי המידע שהוא בנוי ממנו.

  28. 11:11

    אם יש לו פרופרטי שנקרא אימייל אנחנו רוצים לשמור אותו בטבלת אימיילס. אם יש לו פרופרטי שנקרא salary אנחנו רוצים לשמור אותו בטבלת העובדים. אז אם אנחנו רוצים את היכולת הזאת במהלך הריצה להבין מה ה-properties או ה-fields או ה-methods שיש בתוך האובייקט, ככה אנחנו יכולים לקרוא אותם.

  29. 11:36

    אז זאת היא בעצם דוגמה אחת לשימוש ב-reflection. אנחנו הולכים לראות דוגמה נוספת לשימוש ב-reflection, והדוגמה הזאת בכלל עושה משהו אחר.

  30. 11:49

    יכול להיות שיש מצב שבו אנחנו מקבלים איזשהו DLL במהלך הריצה של התוכנית, באופן דינמי, ביחד עם ה-DLL הזה אומרים לנו בדיוק איך ה-DLL נקרא, איך המחלקה שיש בו, המחלקות שיש בו נקראות, איזה שדות, פונקציות, data members, properties, constructors וכו' קיימים שם, אבל מה שאנחנו לא יודעים או שמה שאין לנו זה אין לנו את ה-DLL כאשר אנחנו בונים את האפליקציה.

  31. 12:26

    זאת אומרת, איך אנחנו יכולים לבנות אפליקציה שאמורה לדעת רק כאשר היא רצה על קיומו של איזשהו DLL מסוים ששולחים לה באופן דינמי, ובמהלך חיי האפליקציה אין את ה-DLL הזה, או ליתר דיוק במהלך הפיתוח אין לנו את ה-DLL.

  32. 12:49

    למעשה יש נישה בשוק שמשתמשת עם הקונספט הזה, זה קורה לעיתים נדירות אבל זה קיים בעולם, שבו רק במהלך הריצה אנחנו יודעים על קיומו של טיפוס נתונים, כן אומרים לנו את השמות, כי הרי אנחנו לא יכולים לשים את שם מוישה בתוך first name אם אנחנו לא יודעים שקיים שם משתנה first name כי יכול להיות שיש שם הרבה הרבה משתנים.

  33. 13:15

    אז צריכים להגיד לנו תקשיב יש מחלקה שנקראת person ויש לה field שנקרא first name ויש לה פונקציה שנקראת print ואנחנו רוצים שתיצור אובייקט ממנה תכניס את מוישה לתוך first name ותקרא לפונקציית print.

  34. 13:31

    כל הדבר הזה בצורה דינמית לחלוטין מבלי שיש לנו את המחלקה person בזמן הפיתוח. רק כאשר האפליקציה אצל הלקוח, רק אז דינמית האפליקציה מקבלת dll וצריכה לטעון את הdll ולהשתמש בטיפוסים שלו.

  35. 13:53

    אז הדבר הזה גם ניתן לביצוע על ידי reflection. בואו נראה איך אנחנו יכולים לעשות את זה. דבר ראשון ניקח את המחלקה person שכבר כתבנו ונייצר dll ונכניס את המחלקה הזאת בתוך ה-dll.

  36. 14:13

    נסגור את האפליקציה הנוכחית, נלך ונבנה פרויקט חדש, ניקח class library ונניח אנחנו בונים dll שנקרא business logic, זה בעצם אישויות שאנחנו רוצים להשתמש בהן באפליקציה שלנו.

  37. 14:41

    נפתח את ה-dll הזה, במקום המחלקה class1 נדביק את המחלקה person, נלך ונשנה גם את הקובץ במקום קלאס אחד נקרא לו person.cs רק בכדי שיהיה הגיוני.

  38. 15:02

    נבצע ריבילד עבור הסולושן ונראה שהוא כותב פה למטה ריבילד אול סקסידד אפשר להיפטר פה מכל מיני מרחבי שמות. סבבה והנה יש לנו כאן איזושהי מחלקה בתוך dll אפילו נגדיר אותה פה כפאבליק למרות שלא היינו חייבים.

  39. 15:27

    ואנחנו רוצים לכתוב תוכנית בכלל אחרת לגמרי שלא מכירה את ה-DLL הזה במהלך הפיתוח אלא רק במהלך הריצה. לצורך הדוגמה בואו נבצע סגירה ונפתח פרויקט חדש.

  40. 15:50

    כאן אנחנו רוצים מחלקה שמבצעת שימוש דינמי ב-DLL. זה יהיה Console Application ואנחנו לא רוצים לבצע Add Reference ל-Dלל כי אנחנו לא אמורים לדעת על קיומו.

  41. 16:15

    רק כאשר התוכנית רצה אנחנו אמורים לדעת על קיומו של ה-DLL הזה. אוקיי, אז איך אנחנו בעצם דרך Reflection יכולים ליצור Object Person אם כרגע אין לי את ה-DLL הזה?

  42. 16:32

    אז מה שצריך להיות לי זה כל מיני שמות.

לקורס המלא: קורס תכנות מתקדם ב‑#C ודוט-נט

ההרצאה הקודמת: Reflection - חלק 1

ההרצאה הבאה: תרגילים על Reflection

קורסים נוספים במסלול

  • קורס WinForms - תוכנות רגילות בווינדוס
  • פרויקט מעשי ב-#C - בונים מחשבון פשוט
  • פרויקט מעשי ב-#C - ספר טלפונים
  • פרויקט מעשי ב-#C - תוכנת צייר
  • קורס ADO.NET - חיבור אתר למסד נתונים
  • קורס WCF - תקשורת למתקדמים בדוט-נט