אפשר להמשיך את סדרת הטיפים של Proxy בשני אופנים:
הראשון הוא להתחיל לדון כיצד ניתן לממש Proxy
השני הוא להתחיל לפתוח ולחקור את העולם של Interception (זו הכללה לProxy)
אני אתחיל בסקירת שיטות למימוש Proxy.
כמו שראינו, הדרך הפשוטה ביותר לממש Proxy הוא לממש מחלקה המממשת ממשק ומנתבת את כלל המתודות למתודה מסוימת. זה קצת עבודה, אבל אפשרי לעשות זאת בלי יותר מדי רקע וידע.
הבעיה העיקרית בפתרון הזה, היא שצריך לממש עבור כל סוג ממשק מחלקה כזאת, כלומר לא נוכל לכתוב Proxy גנרי כלשהו. כמובן, זה בלתי מתקבל על הדעת ברוב המקרים, שהרי אם WCF למשל היה דורש מאיתנו לכתוב איזשהו מימוש, דיפולטי ככל שיהיה, לשליחת הודעות לשרת והחזרת תשובה, לא היינו משתמשים בו.
אז מה אפשר לעשות?
הדרך הראשונה לפתור את הבעיה שנסקור היא ע”י ירושה מRealProxy. זוהי מחלקה מהFramework, שכפי שרומז שמה, מאפשרת לנו ליצור Proxyים בצורה פשוטה. כל מה שעלינו לעשות זה לרשת מRealProxy ולדרוס את המתודה ששמה Invoke:
|
|
כעת כדי להשתמש בזה פשוט ניצור Instance ונקרא לפונקציה GetTransparentProxy:
|
|
מגניב ביותר!
אפשר גם לשנות את ערכי ההחזר (כולל הפרמטרים שהם out), ולקבוע Exception וכו’ בעזרת הממשק IMethodReturnMessage (יש טיפוס שנקרא ReturnMessage שמממש אותו שהשתמשנו בו)
איך הדבר הזה עובד?
למעשה יש איזשהו טיפול בCLR שבודק שאם אובייקט מסוים הוא RealProxy, אז מתבצעת הקריאה למתודה לא בצורה הקלאסית שאנחנו מכירים: כל המידע שהועבר לפונקציה בקריאה מועבר לאיזשהו IMessage המכיל את התוכן המתאים, ונקראת הפונקציה Invoke עם הIMessage הנ"ל.
הבעיה העיקרית בשיטה הזו היא שהיא הרבה יותר איטית מקריאה רגילה לפונקציה. אם נערוך איזשהי השוואה נראה כי ההבדלים בין קריאה למתודה ריקה (ללא תוכן) ממחלקה שמממשת ממשק לעומת ממחלקה שיוצרת את הממשק דרך RealProxy הם:
Number of calls | Dummy (in milliseconds) | RealProxy (in milliseconds) |
---|---|---|
10 | 0 | 0 |
100 | 0 | 0 |
1000 | 0 | 4 |
10000 | 0 | 66 |
100000 | 0 | 549 |
1000000 | 9 | 4927 |
10000000 | 99 | 50100 |
יוצא שהקריאות של דרך RealProxy הן יותר מפי 500 יותר איטיות מקריאות למתודה.
מבחינת ביצועים זה לא להיט, אבל בהחלט יש שימוש בזה בFramework. עד כדי כך, שאפילו הProxyים שאנחנו מקבלים מChannelFactory של WCF ממומשים באמצעות RealProxy.
שבוע מיופה כוח טוב!