19-01-16, 02:01 PM
(آخر تعديل لهذه المشاركة : 19-01-16, 03:25 PM {2} بواسطة silverlight.)
السلام عليكم ورحمة الله وبركاته
الهدف
الهدف من هذا الموضوع هو مشاركة الأفكار البرمجية
مقدمة
في الموضوعات السابقة الموجودة في اللينك التالية ناقشنا سريعا كيفية إستخدام Generic Delegates وفي هذا الموضوع سوف نتطرق لبعضا من الأساليب المختلفة التي من الممكن الاستفادة منها من خلال برامجنا
Generic Delegates & ًWindows Forms Control - Part 1
Generic Delegates - Func and Action
مثال
المثال التالي مأخوذ من موقع مايكروسوفت في اللينكـــــــــ وهو يوضح كيفية نسخ مصفوفة الي مصفوفة اخري والهدف من استخدام نفس المثال هو سهولة توضحيح الفارق بين ما كتبته مايكروسوفت و بين ما نريد ان نتطرق له هنا في موضوعنا وما يهمني في مثال مايكروسوفت هو الجزء من الكودالذي يوضح كيفية استخدام Lambada مع Generic Delegates
الكود التالي يوضح شكل الكود الخاص بمايكروسوفت وهو مكتوب للإستخدام مع Console Application
أولا
لنعيد كتابة نفس الكود حتي نستطيع استخدامه مع الويندوز فورم وذلك قبل التعمق في تطويره وهنا سوف أعيد كتابة المثال ليصلح للاستخدام مع ListBox تحديدا ولتنفيذ الكود نحتاج الي فورم موجود عليهListBox
سنلاحط في الكود أن مايكروسوفت تمرر دالة و ليس روتينا الي Generic Action و هذا يؤكد ما سبق و قلته سابقا ان Generic Delegates تقبل أن نمرر لها إما دالة Function او روتين Sub
و الكود التالي هو إعادة لصياغة نفس الكود أعلاه و لكننا هنا نمرر روتين Sub
السؤال الأن هل انا في حاجة الي تمرير البيانات الي Generic Delegates في صورة دالة أو في صورة روتين وهل يمكن الاستغناء عن هذا كله و الإجابة ستكون بالطبع ممكن ان نفعل هذا
و الكود التالي يوضح كيفية ان نفعل هذا عن طريقة تمرير البيانات بشكل مباشر و في صورة روتين
و الكود التالي يوضح كيفية ان نفعل هذا عن طريقة تمرير البيانات بشكل مباشر في صورة دالة
طبعا هناك كمية من الأسئلة قد يتطرق اليها ذهن أي مبرمج
ماهي الفائدة من كل هذا ؟
أنا لست محتاجا لكتابة الكود بهذه الطريقة؟
ساستخدم الأساليب القديمة في كتابة الكود؟
العملية مش ناقصة تضييع وقت؟
العملية مش ناقصة صداع أصلا؟
الحقيقة أنا في بداية استخدامي لنفس الأسلوب في كتابة الكود حاولت أن أقنع نفسي ب أنني لا أكتب شيئا جديداولكن بعد ان أضعت يوما كاملا في دراسة الموضوع وأيضا و كلما تقدمت في دراسة الموضوع بدأت الصورة تتضح لي بشكل افضل و اكتشفت أنني كنت مخطئا في تساؤلاتي
والحقيقة كان أهم سؤال أردت ان أسمع إجابته هو
لماذا مايكروسوفت طورت مثل هذا الاسلوب في البرمجة
هناك مثل مصري قديم يقول الحداية لايمكن أت ترمي كتاكيت او بمعني اخر لماذا مايكروسوفت قد تضيع وقتها و فلوسها في تطوير مثل هذه الاساليب
وهنا سألت نفسي اليس Generic Delegates عبارة عن EventHandler اذا من الممكن ان نستخدمها من داخل اي كلاس مثلما نفعل مع اي EventHandler و أيضا اليس علينا ان نقوم بعممل Dispse لها
ومنا أعدت كتابة وصياغة الكود أعلاه ليأخذ شكل الكلاس التالي
الكود التالي يوضح كيفية استخدام الكلاس اعلاه من داخل الفورم
طبعا من الافضل ان نكتب الدوال او الروتينيات التي سوف تقوم بكل العمل المطلوب في نسخ المصفوفات داخل الكلاس السابق نفسه أو في كلاس منفصل او علي شكل Interface و لكن لهذا حديث اخر
عموما وعلي ما اعتقد اننا قد نكتب الكود الذي يقوم بكل العمل في شكل Interface و نمرر فقط مدخلات Interface ثم في الفورم نطبق فقط الكود و نستخدم Generic Action
و ربما و الله أعلم ان تلك هي الفائدة الرئيسية او الهدف الاساسي من بناء Generic Action
لكن ومن الواضح هنا هو اننا نستطيع اطلاق حدث به روتينات او دوال تقوم بتنفيذ بعض الكود ثم وفي النهاية نستطيع التخلص من كل هذا عن طريق عمل Dispose متهيألي ان الاسلوب هذا مناسب جدا لكتابة كلاسات يسهل تنفيذها و التخلص منها بدون التأثير علي ذاكرة الكمبيوتر
اخر شئ وبما أنني من عشاق الجرافكس و الرسم كان صعب جدا أن أفوت فرصة استخدام الاسلوب الذي نناقشه في الجرافكس و الأكواد التالية توضح بعضا من هذه الأفكار
الكود التالي يوضح كيفية استخدام الكلاس اعلاه لرسم مستطيل علي الفورم
في المرفقات ستجدون نسخة من الكود مكتوب بنسخة الفيجوال استوديو 2015
تقبلوا تحياتي
الهدف
الهدف من هذا الموضوع هو مشاركة الأفكار البرمجية
مقدمة
في الموضوعات السابقة الموجودة في اللينك التالية ناقشنا سريعا كيفية إستخدام Generic Delegates وفي هذا الموضوع سوف نتطرق لبعضا من الأساليب المختلفة التي من الممكن الاستفادة منها من خلال برامجنا
Generic Delegates & ًWindows Forms Control - Part 1
Generic Delegates - Func and Action
مثال
المثال التالي مأخوذ من موقع مايكروسوفت في اللينكـــــــــ وهو يوضح كيفية نسخ مصفوفة الي مصفوفة اخري والهدف من استخدام نفس المثال هو سهولة توضحيح الفارق بين ما كتبته مايكروسوفت و بين ما نريد ان نتطرق له هنا في موضوعنا وما يهمني في مثال مايكروسوفت هو الجزء من الكودالذي يوضح كيفية استخدام Lambada مع Generic Delegates
الكود التالي يوضح شكل الكود الخاص بمايكروسوفت وهو مكتوب للإستخدام مع Console Application
PHP كود :
Public Module TestLambda
Public Sub Main()
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Dim copyOperation As Action(Of String(), String(), Integer) = _
Sub(s1, s2, pos) CopyStrings(s1, s2, pos)
copyOperation(ordinals, copiedOrdinals, 3)
For Each ordinal As String In copiedOrdinals
If String.IsNullOrEmpty(ordinal) Then
Console.WriteLine("<None>")
Else
Console.WriteLine(ordinal)
End If
Next
End Sub
Private Function CopyStrings(source() As String, target() As String, startPos As Integer) As Integer
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
Return source.Length - startPos
End Function
End Module
أولا
لنعيد كتابة نفس الكود حتي نستطيع استخدامه مع الويندوز فورم وذلك قبل التعمق في تطويره وهنا سوف أعيد كتابة المثال ليصلح للاستخدام مع ListBox تحديدا ولتنفيذ الكود نحتاج الي فورم موجود عليهListBox
PHP كود :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Dim copyOperation As Action(Of String(), String(), Integer) = Sub(s1, s2, pos) CopyStrings(s1, s2, pos)
copyOperation(ordinals, copiedOrdinals, 3)
For Each ordinal As String In copiedOrdinals
If Not String.IsNullOrEmpty(ordinal) Then
ListBox1.Items.Add(ordinal)
End If
Next
End Sub
Private Function CopyStrings(source() As String, target() As String, startPos As Integer) As Integer
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
Return source.Length - startPos
End Function
End Class
سنلاحط في الكود أن مايكروسوفت تمرر دالة و ليس روتينا الي Generic Action و هذا يؤكد ما سبق و قلته سابقا ان Generic Delegates تقبل أن نمرر لها إما دالة Function او روتين Sub
و الكود التالي هو إعادة لصياغة نفس الكود أعلاه و لكننا هنا نمرر روتين Sub
PHP كود :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Dim copyOperation As Action(Of String(), String(), Integer) = Sub(s1, s2, pos) CopyStrings(s1, s2, pos)
copyOperation(ordinals, copiedOrdinals, 3)
For Each ordinal As String In copiedOrdinals
If Not String.IsNullOrEmpty(ordinal) Then
ListBox1.Items.Add(ordinal)
End If
Next
End Sub
Private Sub CopyStrings(source() As String, target() As String, startPos As Integer)
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
End Sub
End Class
السؤال الأن هل انا في حاجة الي تمرير البيانات الي Generic Delegates في صورة دالة أو في صورة روتين وهل يمكن الاستغناء عن هذا كله و الإجابة ستكون بالطبع ممكن ان نفعل هذا
و الكود التالي يوضح كيفية ان نفعل هذا عن طريقة تمرير البيانات بشكل مباشر و في صورة روتين
PHP كود :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Dim copyOperation As Action(Of String(), String(), Integer) = Sub(source() As String, target() As String, startPos As Integer)
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
End Sub
copyOperation(ordinals, copiedOrdinals, 3)
For Each ordinal As String In copiedOrdinals
If Not String.IsNullOrEmpty(ordinal) Then
ListBox1.Items.Add(ordinal)
End If
Next
End Sub
End Class
و الكود التالي يوضح كيفية ان نفعل هذا عن طريقة تمرير البيانات بشكل مباشر في صورة دالة
PHP كود :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Dim copyOperation As Action(Of String(), String(), Integer) = Function(source() As String, target() As String, startPos As Integer)
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
Return source.Length - startPos
End Function
copyOperation(ordinals, copiedOrdinals, 3)
For Each ordinal As String In copiedOrdinals
If Not String.IsNullOrEmpty(ordinal) Then
ListBox1.Items.Add(ordinal)
End If
Next
End Sub
End Class
طبعا هناك كمية من الأسئلة قد يتطرق اليها ذهن أي مبرمج
ماهي الفائدة من كل هذا ؟
أنا لست محتاجا لكتابة الكود بهذه الطريقة؟
ساستخدم الأساليب القديمة في كتابة الكود؟
العملية مش ناقصة تضييع وقت؟
العملية مش ناقصة صداع أصلا؟
الحقيقة أنا في بداية استخدامي لنفس الأسلوب في كتابة الكود حاولت أن أقنع نفسي ب أنني لا أكتب شيئا جديداولكن بعد ان أضعت يوما كاملا في دراسة الموضوع وأيضا و كلما تقدمت في دراسة الموضوع بدأت الصورة تتضح لي بشكل افضل و اكتشفت أنني كنت مخطئا في تساؤلاتي
والحقيقة كان أهم سؤال أردت ان أسمع إجابته هو
لماذا مايكروسوفت طورت مثل هذا الاسلوب في البرمجة
هناك مثل مصري قديم يقول الحداية لايمكن أت ترمي كتاكيت او بمعني اخر لماذا مايكروسوفت قد تضيع وقتها و فلوسها في تطوير مثل هذه الاساليب
وهنا سألت نفسي اليس Generic Delegates عبارة عن EventHandler اذا من الممكن ان نستخدمها من داخل اي كلاس مثلما نفعل مع اي EventHandler و أيضا اليس علينا ان نقوم بعممل Dispse لها
ومنا أعدت كتابة وصياغة الكود أعلاه ليأخذ شكل الكلاس التالي
PHP كود :
Public Class CopyArrayAction
Implements IDisposable
Private copyAction As Action(Of String(), String(), Integer)
Private disposedValue As Boolean
Public Sub New(source() As String, target() As String, startPos As Integer, currentAction As Action(Of String(), String(), Integer))
SourceArray = source
TargetArray = target
StartPosition = startPos
copyAction = currentAction
' initialize Action
copyAction(source, target, startPos)
End Sub
Public ReadOnly Property SourceArray As String()
Public ReadOnly Property TargetArray As String()
Public ReadOnly Property StartPosition As Integer
Protected Overridable Sub Dispose(disposing As Boolean)
If disposedValue Then
Return
End If
If disposing Then
If copyAction IsNot Nothing Then
copyAction(SourceArray, TargetArray, StartPosition)
copyAction = Nothing
End If
End If
disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
End Sub
End Class ' CopyArrayAction - incomplete class
PHP كود :
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim ordinals() As String = {"First", "Second", "Third", "Fourth", "Fifth"}
Dim copiedOrdinals(ordinals.Length - 1) As String
Using copyAction= New CopyArrayAction(ordinals, copiedOrdinals, 3, Sub(source, target, startPos)
If source.Length <> target.Length Then
Throw New IndexOutOfRangeException("The source and target arrays must have the same number of elements.")
End If
For ctr As Integer = startPos To source.Length - 1
target(ctr) = String.Copy(source(ctr))
Next
End Sub)
For Each s As String In copyAction.TargetArray
If Not String.IsNullOrEmpty(s) Then
ListBox1.Items.Add(s)
End If
Next
End Using
End Sub
End Class
طبعا من الافضل ان نكتب الدوال او الروتينيات التي سوف تقوم بكل العمل المطلوب في نسخ المصفوفات داخل الكلاس السابق نفسه أو في كلاس منفصل او علي شكل Interface و لكن لهذا حديث اخر
عموما وعلي ما اعتقد اننا قد نكتب الكود الذي يقوم بكل العمل في شكل Interface و نمرر فقط مدخلات Interface ثم في الفورم نطبق فقط الكود و نستخدم Generic Action
و ربما و الله أعلم ان تلك هي الفائدة الرئيسية او الهدف الاساسي من بناء Generic Action
لكن ومن الواضح هنا هو اننا نستطيع اطلاق حدث به روتينات او دوال تقوم بتنفيذ بعض الكود ثم وفي النهاية نستطيع التخلص من كل هذا عن طريق عمل Dispose متهيألي ان الاسلوب هذا مناسب جدا لكتابة كلاسات يسهل تنفيذها و التخلص منها بدون التأثير علي ذاكرة الكمبيوتر
اخر شئ وبما أنني من عشاق الجرافكس و الرسم كان صعب جدا أن أفوت فرصة استخدام الاسلوب الذي نناقشه في الجرافكس و الأكواد التالية توضح بعضا من هذه الأفكار
PHP كود :
Public Class CairoPainter
Implements IDisposable
Private paintAction As Action(Of Control, Graphics, Color, Rectangle)
Private disposed As Boolean
Public Sub New(ctrl As Control, g As Graphics, clr As Color, rect As Rectangle, action As Action(Of Control, Graphics, Color, Rectangle))
paintAction = action
paintAction(ctrl, g, clr, rect)
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
If disposed Then
Return
End If
If disposing Then
' dispose paintAction
If paintAction IsNot Nothing Then
paintAction = Nothing
End If
End If
disposed = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
End Sub
End Class
الكود التالي يوضح كيفية استخدام الكلاس اعلاه لرسم مستطيل علي الفورم
PHP كود :
Protected Overrides Sub OnPaint(e As PaintEventArgs)
MyBase.OnPaint(e)
Dim rect As Rectangle = New Rectangle(10, 10, 100, 100)
Using New CairoPainter(Me, e.Graphics, Color.Black, rect, Sub(ctrl, g, clr, r) Draw(ctrl, g, clr, r))
' do nothing as the generic action will take care of the paint and will disposed
End Using
Using New CairoPainter(Me, e.Graphics, Color.Black, rect, Sub(ctrl, g, clr, r)
' draw what you want here
End Sub)
' do nothing as the generic action will take care of the paint and will disposed
End Using
End Sub
Private Sub Draw(c As Control, g As Graphics, clr As Color, rect As Rectangle)
Dim sb As New SolidBrush(clr)
g.FillRectangle(sb, rect)
End Sub
في المرفقات ستجدون نسخة من الكود مكتوب بنسخة الفيجوال استوديو 2015
تقبلوا تحياتي