سلام بچه ها کسی میتونه در مورد delegate یا نماینده در سی شارپ و کاربردش و نحوه کار توضیح بده این سایت های خارجی این قدر پیچوندند قضیه رو هیچی نفهمیدم :n13:
Printable View
سلام بچه ها کسی میتونه در مورد delegate یا نماینده در سی شارپ و کاربردش و نحوه کار توضیح بده این سایت های خارجی این قدر پیچوندند قضیه رو هیچی نفهمیدم :n13:
دلیگیت متاسفانه یکی از سخت ترین مباحث برنامه نویسی میباشه که من شخصا برا فهمیدنش، بیش از ۸-۹ پک اموزش برنامه نویسی رو از اول تا اخر خوندم یا تماشا کردم که چیزی رو از دست ندم که موقع صحبتش در مورد دلیگیت، بفهمم ماجراش چیه!!!!!
الی ایحال، دلیگیت یه نوع میباشه(مثل کلاس و ساختار و ...) که شما میسازی تا با استفاده از اون، بتونی چند ترد یا تابع رو به صورت همزمان فراخوانی بکنی...!!!
فرضا میخوای یه مقدار ثابت رو به چند تابع بدی و همه رو با هم فراخوانی بکنی!
یا مثلا میخوای داخل یه تابع، یه تابع دیگه رو فراخوانی بکنی(پارامترش!) که خود اون تابعه یه تابع دیگس! یعنی سه لایه که باز از دلیگیت ها استفاده میشه...:n04:
کلا دلیگیت سخت ترین قسمت برنامه نویسی هستش و اگر کسی بتونه مطلبی بیاره که به خوبی به ادم یاد بده که چیه(شاید کمتر نیاز باشه!) و چطوری ازش درست استفاده بکنیم، یه بار سنگینی رو از روی دوش من برداشته! :)
پاسخ از [ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ] نیز بهره می برد.
این پست کاملا به حروف بزرگ و کوچک حساس هست.
به این علت که delegate با Delegate یک Alias نیستند مانند Int32 و int
به علت طولانی بودن مطلب خواشمند است کمی حوصله کنید.:n11:
در اینجا منظور از کاربر، برنامه نویس می باشد! نه کاربری که با UI کار می کند.
-------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------
delegate یا وکیل.
هدف: نماینده یک متد.
کاربرد: فراخوان یک متد که در هنگام برنامه نویسی این متد مشخص نیست.
ویژگی: توانایی در هندل کردن تمامی متد ها با ساختار تعریفی خود. ایجاد یک فالب برای یک متد.
مفهوم: در راستای تعریف Anonymous Method
مثال:
Event ها : شما در حال تعریف یک کلاس هستید که در برخی موارد نیاز هست تا یک رویداد را فراخوانی کند. خوب آیا شما می دانید کاربر چه متدی را به رویداد شما متصل می کند؟ مطمئنا خیر. پس یک قالب برای متد خود تعریف می کنید و کاربر را مستلزم ارائه یک متد با آن قالب می کنید. مثال:
فرض کنید چنین کلاسی داریم:
و چنین فرمی هم داشته باشیم:کد:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testAnswerP30world
{
class TestClass
{
public delegate void ImComming();
public delegate void ImLate(int location);
public event ImComming OnIamComming;
public event ImLate OnIamLate;
public int LocationPoint
{
get;
set;
}
public void WhereAreYou() {
bool status=false;
if (LocationPoint < 10)
status = true;
if (status)
{
if (OnIamComming != null)
OnIamComming();
}
else
if (OnIamLate != null)
OnIamLate(LocationPoint + 100);
}
}
}
خوب همان طور که می بینید ما ابتدا دو قالب برای رویداد های خودمون توسط delegate تعریف کردیم. یکی آرگومان ورودی ندارد و دیگری نیازمند یک آرگومان عددی است. پس کاربر هنگام اتصال یک متد باید یک متد با اون ویژگی ارائه کند. همان طور که در فرم می بینید. آیا در هنگام نوشتن کلاس ما می دانستیم نام متد مورد نظر کاربر چیست که آنرا فراخوانی کنیم؟ یا اصلا می دانستیم که اون متد در چه کلاسی و کجاست؟کد:using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace testAnswerP30world
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
TestClass tsc = new TestClass();
private void Form1_Load(object sender, EventArgs e)
{
tsc.OnIamComming += tsc_OnIamComming;
tsc.OnIamLate += tsc_OnIamLate;
}
private void button1_Click(object sender, EventArgs e)
{
tsc.LocationPoint = int.Parse(textBox1.Text);
tsc.WhereAreYou();
}
void tsc_OnIamLate(int location)
{
MessageBox.Show("I am Late.... "+location.ToString()+" far");
}
void tsc_OnIamComming()
{
MessageBox.Show("I am Comming......");
}
}
}
در Invoke کردن (خواهش کردن!)
شما زمانی که بخواهید یک تغییر خاص در عناصر یک Thread دیگر بدهید که آن Thread پیوسته به آن ها پاسخ می دهد می توان از delegate استفاده کرد. کجا؟ فرض کنید که بخواهید توسط یک Thread دیگر به عناصر روی فرم دسترسی پیدا کنید. چه اتفاقی می افتد؟ مطمئنا در دام CrossThread گیر خواهید افتاد. (البته بیشتر برنامه نویس ها با تغییر پراپرتی System.Windows.Forms.Form.CheckForIllegalCrossThre adCalls این عمل را غیر فعال می کنند که اصلا پیشنهاد نمی گردد.)
خوب برای رفع مشکل باید عنصر مورد نظر را Invoke کنید. در یک شرح به زبان ساده:
Thread اول: textboxت رو به من می دهی؟
Thread دوم: نه!
CrossThread روی می دهد!!!
با Invoke :
Thread اول: ای وکیل عزیزم. برو ببین می تونی از Thread دوم textboxش رو قرض بگیری؟
وکیل: ای Thread دوم. ای بزرگوار:n02: . خواهشا ( مفهوم Invoke) اون textBoxت رو به من قرض می دهی؟
Thread دوم: آره جیگرم!
به بخش های برجسته دقت کنید.
خوب بحث رو به حالت قبل بر می گردونم. پس به این کد دقت کنید:
همان طور که می بینید من از Thread اصلی کل فرم را قرض می گیرم. :n02: ( این کار هم اصولی نیست چون من کل فرم رو که احتیاج ندارم.اما کلی گفتم.)کد:
System.Threading.Thread p1;
private void Form1_Load(object sender, EventArgs e)
{
p1 = new System.Threading.Thread(new System.Threading.ThreadStart(Run));
p1.Start();
}
delegate void ChangeTextBox(string text);
void Run() {
string tempString="Salam";
if (this.InvokeRequired)
this.Invoke(new ChangeTextBox(TextChanger),tempString);
else
TextChanger(tempString);
}
void TextChanger(string data) {
textBox1.Text = data;
}
حالا می تونم به textBox دسترسی داشته باشم پس تابع خودم رو به وکیلم می دهم تا آنرا برای Thread اصلی معرفی کند. حال Thread اول منتظر می شود تا اون وکیل کارش تموم بشه و بعد دوباره سرویس دادن رو شروع بکنه.
نکات این بخش:
1- در ابتدای کار که Thread رو تعریف می کنیم، کلاس ThreadStart تعریف می شود که اون هم وکیل هست تا Thread مورد تعریفیم بدونه که تابعی رو که باید اجرا کنه چیه.
2- در Invoke کردن هر دو Thread درگیر می شوند. پس اگر تابع اجرا در Invoke مشغول شود هردو Thread تعطیل می شوند.
Invoke توسط مارشال:
زمانی این Invoke مورد استفاده هست که بخواهیم یک عنصر را از یک فایل خارجی مانند COM ها قرض بگیریم. از اونجا که در این فایل ها حافظه ها unmanaged هستند ممکن است که یک تابع را به صورت FunctionPointer برگردونند. پس لازم است تا یک اشاره گر به یک متد تبدیل شود. برای این تبدیل ما تابعی رو که فراخوانی می کنیم می دانیم چه ساختاری دارد پس باید این ساختار را در برنامه نویسی توسط delegate ایجاد کنیم. سپس این وکیل را به Marshal ارائه کنیم. به این مثال دقت کنید:
GetProcAddress یک تابع از Kernel32 هست و ما در قبل یک Dll رو توسط LoadLibrary همان Kernel32 بارگذاری کردیم. حالا می خواهیم تابعمون رو فراخوانی کنیم. پس delegate خودمون رو مثلا این طوری تعریف می کنیم:کد:IntPtr functionPtr = GetProcAddress(dllPtr, "myFunc");
myFunc_Delegate MainMyFunc = (myFunc_Delegate)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(myFunc_Delegate));
در خط دوم کد اصل مطلب اتفاق می افتد. یک پویتنر به مارشال می دهیم. خوب اون بنده خدا از کجا بدونه که ساختار تابع ما در حافظه چه شکلیه!!! پس با یک delegate ساختار حافظه خود را رائه کردیم. از اونجایی هم که تابع برگشتی از نوع Delegate هست ( توضیحات Delegate در ادامه) می بایست مشخصه آن معلوم شود پس با یک cast آنرا به تابع خود تبدیل می کنیم. حالا MainMyFunc که یک وکیل مجهز است را می توانیم اجرا کنیم:کد:private delegate int myFunc_Delegate(int devIndex, ref int IDret);
و کاربردهای دیگر.....کد:MainMyFunc(i, ref devID);
اصل مطلب delegate همین هاست اگرچه می تواند در جاهای مختلف به شکل های مختلف استفاده شود.
Delegate:
هدف: مدیریت عناصر delegate .
کاربرد: کاملا کردن کاستی های تعریف delegate .
ویژگی: توانایی هندل انواع مختلف delegate .
مفهوم: در راستای تعریف delegate .
اگر delegate را متوجه شده باشید فهم Delegate کار دشواری نیست. در Delegate شما می توانید delegate ها را با شرایط متفاوت بسازید. همین!
حالت اول:
این حالت عموما توسط یک Type است. این بدان معناست که در RunTime یک delegate با توجه به شرایط بسازید.
مثال:
این حالت در زمانی مناسب است که شما تابع یا کلاسی را که می خواهید استفاده کنید را با شرایط خاص به کار ببرید. یک مثال ساده آن این است که شما می خواهید 100 تابع را از یک کلاس اجرا کنید. کافیست تا اسامی آن ها را داشته و توسط یک حلقه اسامی را با حالت بالا اجرا کنید.کد:
delegate void myFuncStructure();
private void Form1_Load(object sender, EventArgs e)
{
TestClass tsc = new TestClass();
tsc.OnIamComming+=tsc_OnIamComming;
System.Reflection.MethodInfo myFuncInfo=tsc.GetType().GetMethod("WhereAreYou", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
myFuncStructure mainFunc=(myFuncStructure)Delegate.CreateDelegate(typeof(myFuncStructure),tsc ,myFuncInfo);
mainFunc();
}
void tsc_OnIamComming()
{
MessageBox.Show("Run on Reflection");
}
توضیح کد:
توضیح ندارد! اون قدر هم ساده نیست اما توضیحش می ره در یک مبحث دیگه.
حالت دوم:
مدیریت یکسری delegate :
به طور مثال یک آرایه از delegate ها. یک List و ....
مثال: همان پستی که در بالا بیان شد.
حالت سوم:
در خواست از کاربر برای معرفی یک متد با هر شکل و قیافه ای در آرگومان.
به این مثال توجه کنید:
و کلاس دوم این طوری باشه:کد:
delegate void IsGet();
private void Form1_Load(object sender, EventArgs e)
{
TestClass2 tsc2 = new TestClass2();
tsc2.RunYourFuncWithoutArg(new IsGet(GetIt));
}
public void GetIt() {
MessageBox.Show("Salam");
}
برای اینکه ار بابت نوع آرگومان های متد ارسالی کاربر مطلع شویم باید از این استفاده کنیم:کد:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace testAnswerP30world
{
class TestClass2
{
public void RunYourFuncWithoutArg(Delegate method) {
method.DynamicInvoke();
}
}
}
و موارد دیگر........کد:method.Method.GetGenericArguments();
در هر صورت چه d یا چه D هدف یک چیز است: متدی که معلوم نیست چیه.
تمام کد ها کامل هست و با کپی کردن براحتی اجرا خواهند شد لذا بخش های مختلف را بررسی کنید تا درک بهتری پیدا کنید.
موفق باشید.
سلام..من هرچی گشتم دکمه ثبت تشکر رو ندیدم برا همین اینطوری تشکر میکنم..دمت گرم داداش بابت توضیحات خیلی خوبت...:n16::n18:
ممنون از آموزش خوبت:n18:
ای کاش مدیر زحمت ادقام کردن دو تا آموزش های آقای [ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ] و مهم کردن اونش و هم جنین حذف پست های اضافی رو میکشید به خدا حیفه یک همچین مطالبی خاک بخورند!
سلام
بخشی با عنوان کلمات کلیدی به [ برای مشاهده لینک ، با نام کاربری خود وارد شوید یا ثبت نام کنید ] اضافه شد.
دوستان در صورت مشاهده توضیح مناسبی از سایر کلمات کلیدی ، با پیام خصوصی اطلاع دهند تا فهرست فوق تکمیل تر گردد.
موفق باشید.