RSS

Monthly Archives: May 2010

تصدير البيانات من ملف إكسل إلى قواعد بيانات SQL SERVER


سوف نتحدث اليوم عن كيفية تصدير البيانات من ملف إكسل (Excel) إلى قواعد بيانات (MS SQL Server) ولكن قبل أن نبدء هنالك قواعد يجب أن تتبع
•    يجب أن تضع عناوين (Header)  للبيانات التي لديك في الصف الأول بمعنى أخر يجب أن تكون لديك أعمدة ذات أسماء كما هو موضح في الصور التالية

•    يجب أن تقوم بتصميم جدول في قاعدة بيانات (SQL Server) بنفس الأسماء إذا أردت (غير ضروري) مع إختيار أنواع البيانات المناسبة (Data Type) مثلا (int,varchar2,numeric…). مع أهمية الترتيب في تصميم الأعمدة فكما ترى في الأعلى لدينا ملف أكسل يحتوي على عمود إسمه (ID) وعمود أخر إسمه (Name).إذا عند تصميم الجدول تنشيء عمود إسم (ID) ثم عمود أخر إسمه (Name) على التوالي.
والان بعد أن رأينا القواعد نأتي الان الى صلب الموضوع وهو كيف يمكن كتابة شفرة (Code) لنقل الملفات
حتى نسهل الموضوع سوف أضع الشفرة على أجزاء بخطوات
اولا نضع معلومات الخاصة بنص الإتصال (Connection String) في متغير نصي

string excelConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\xls\\ExcelFile.xls ;Extended Properties=Excel 8.0";

طبعا هذه المعلومات ثابتة ماعدا جزئية مسار ملف الاكسل يجب عليك تغيرها الى مسار ملفك
ثانيا قم بالإتصال بقاعدة البيانات عن طريق إستخدام (OleDbConnection) وقم بإرسال نص الإتصال إليه

using (OleDbConnection connection =
new OleDbConnection(excelConnectionString))
{

ثالثا قم بإنشاء كائن من نوع (OleDbCommand)   واكتب إستعلام الإختيار (Select Statment) وايضا حدد له كائن الإتصال كالتالي

OleDbCommand command = new OleDbCommand
("Select * FROM [Sheet1$]", connection);

لاحظ معي جملة الإتصال ولاحظ أن إسم الجدول هو إسم الورقة (Sheet) طبعا يمكنك تغيره من ملف إكسل ولاحظ أيظا أنك يجب أن تتبعها مباشرة وبدون فواصل رمز الدولار($)

رابعا قم بفتح الإتصال

connection.Open();

خامسا قم بتنفيذ الإستعلام  بإستخدام الدالة (ExecuteReader)

using (DbDataReader reader = command.ExecuteReader())
{

الأن فإن جميع البيانات الموجودة في ملف إكسل تم تصديرها وأصبحت موجودة في كائن من نوع (DbDataReader)
بعد أن قمنا بتصدير البيانات وإسنادها يأتي الان العمل على جزئية قواعد بيانات (SQL SERVER)
أولا نضع معلومات الخاصة بنص الإتصال (Connection String) في متغير نصي

string sqlConnectionString = "Data Source=Your DataSource;Initial Catalog=Your DataBase;Integrated Security=True";

لاحظ معي أنه يجب أن تكتب إسم مصدر البيانات ( DataSource) بعد ذلك إسم قاعدة البيانات (Initial Catalog)
ثانيا إستخدام كائن من نوع (SqlBulkCopy)  والغرض من ذلك أن هذا الكائن(object) يقوم بنقلة كتلة (Bulk) من البيانات من مصدر إلى مصدرأخر بطريقة فعالة جدا جدا خاصة إذا كان حجم البيانات كبير جدا ونقوم بارسال نص الإتصال إليه  كالتالي.

using (SqlBulkCopy bulkCopy =  new SqlBulkCopy(sqlConnectionString))
{

ثالثا نستخدم خاصية (DestinationTableName) والتي من خلالها نحدد إسم الجدول الذي نريد أن نصدر إليه البيانات في قاعدة بيانات (MS SQL SERVER)

bulkCopy.DestinationTableName = "Table Name";

رابعا واخير نقوم بإستخدام دالة (WriteToServer) والتي تقوم بكتابة البيانات الي المصدر ونرسل لها الكائن من نوع (DbDataReader)

bulkCopy.WriteToServer(dr);

الشفرة كاملة

bulkCopy.WriteToServer(reader);
// Connection String to Excel Workbook
string excelConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=! ;Extended Properties=Excel 8.0

// Create Connection to Excel Workbook
using (OleDbConnection connection =
new OleDbConnection(excelConnectionString))
{
OleDbCommand command = new OleDbCommand
("Select * FROM [Sheet1$]", connection);

connection.Open();

// Create DbDataReader to Data Worksheet
using (DbDataReader dr = command.ExecuteReader())
{
// SQL Server Connection String
string sqlConnectionString = "Data Source=!;Initial Catalog=!;Integrated Security=True";

// Bulk Copy to SQL Server
using (SqlBulkCopy bulkCopy =
new SqlBulkCopy(sqlConnectionString))
{
bulkCopy.DestinationTableName = "!";
bulkCopy.WriteToServer(dr);
}
}
}

لاحظ معي أن أي شيء وضعت عليه علامة (!) تحتاج إلى تغيره إذا أردت أن يتنفذ البرنامج في جهازك
الفائدة الحقيقة
قد يسئل البعض مالذي سوف أستفيده من توريد البيانات من ملف إكسل الى قواعد البيانات ولكي أجيبك عن هذا التساؤل سوف أضح لك حالات حقيقية ( Real Cases)

الحالة الأولى تحويل البيانات من قاعدة بيانات إلى قاعدة بيانات (SQL SERVER)
الأن تخيل لو أن لديك قاعدة بيانات (Oracle,Sybase,MySql..etc) وتريد أن تحول البيانات من قواعد البيانات السابقة الى قاعدة بيانات (SQL SERVER) بناء على قرارات إدارية ماذا سوف تفعل .
طبعا هنالك أدوات تحويل ومن هذه الأدوات (SQL Server Integration Services (SSIS ولكن في بعض الحالات وهي كثيرة جدا لايمكن نقل البيانات على الأقل كليا فقد تجد أن بعضها تم نقله والبعض الأخر لم يتم نقله.فأفضل حل في هذه الحالة هو أن تقوم بتصدير (Export) جميع البيانات إلى ملف ومن ملف إكسل تقوم بتوريدها (Import) إلى قواعد بيانات (SQL SERVER) طبعا معظم المحررات (Editors) الخاصة بقواعد البيانات مثل برنامج (Toad) وغيرها الكثير لديها إمكانية توريد إلى إكسل (Export to Excel).
الحالة الثانية

تخيل معي لو أنك في منظمة وأرادو منك بناء نظام له علاقة بقواعد البيانات ولايوجد لديهم قواعد بيانات بعد وكل البيانات لديهم يتم تخزينها في ملفات إكسل فطبعا سوف تستخدم هذه الطريقة بلاشك .
الخلاصة
في ماسبق تدارسنا سوية كيف يمكن تصدير البيانات الى قواعد بيانات (SQL SERVER) من ملفات إكسل ورأينا سوية القيم الحقيقة لهذا الأسلوب والحالات الحقيقة التي قد تواجهك وكيف يمكن حلها.وطبعا لاأنسى أن أقول لكم أن هنالك طرق أخرى لنقل البيانات مثل إستخدام جملة الإدخال (Insert Statment) ولكن أكثرها فعالية في الإداء هو نقل البيانات ككتلة بإستخدام (SQLBulk) وفي الختام أتمنى أن أكون قد وفقت في الطرح
والله أعلم

رابط التحميل :من هنا

 
5 Comments

Posted by on May 26, 2010 in ASP.NET

 

Tags: , , , ,

المميزات الجديدة في لغة Covariance and Contravariance – C# 4.0


بسم  الله الرحمن الرحيم

سوف أكمل في هذا الدرس السلسة المتعلقة بالمميزات الجديدة بالغة السي شارب وهذه المرة سوف نتحدث إن شاء الله عن Covariance وأيضا عن Contravariance فلنبدء على بركة الله .

أولا : نطاق عمل Covariance & Contravariance

ماقصده بالنطاق هنا هو المكان التي يتم فيه تطبيق مبدء Covariance & Contravariance وهو كالتالي

•    Generic Delegates & InterFaces

•    Reference Types

ثانيا : تعريف Covariance & Contravariance
Covariance
المقصود بمصطلح (Covariance) هو إرجاع أنواع أكثر إشتقاقا ( Derived Classes) من الدالة (Method ) التي قيمتها المرجعة عبارة عن نوع أقل إشتقاقا وهذا النوع يسبقه الكلمة المعرفة ( Out).ويجب ان تعلم أنه فقط يستخدم مع القيم المرجعة فقط ( Return Types) من الدالة التي تم إستدعائها
Contravariance
المقصود بمصطلح (Contravariance) هو إرسال قيمة أقل إشتقاقا ( Base Classes) إلى دالة ( Method) تأخذ قيم أو تقبل حقول أكثر إشتقاقا ( Derived Classes) وهذا النوع يسبقه الكلمة  المعرفة (In). ويجب أن تعلم أنه فقط يستخدم كإرسال قيم الى الدالة وليس لإسترجاع قيم منها .
قد يبدو الوضع معقدا بعض الشيء ولكن الموضوع كله يتعلق بمباديء الوراثة المتعارفة لدى الجميع ومع الشرح أكثر وإعطاء امثلة سوف نفهم جميعا إن شاء الله مالمقصود  بالمصطلحين السابقين.

ثالثا كيف يمكن أستخدام Covariance & Contravariance
أولا مع Generic Delegates
لنأخذ أحد انواع المفوضات (Delegate ) الموجودة في أطار عمل دوت نت ( .Net FrameWork) وهو المفوض (Func<>) أنظر الى الصورة التالية قبل أن نبدء

كما ترى فإن هذا المفوض (Delegate) يقبل أنواع أقل أشتقاقا في الحقل الأول ويقوم بإرجاع أنواع أكثر إشتقاقا في الحقل الثاني .
لنأخذ مثلا حتى تتضح لنا الصورة

class Program
{
static void Main(string[] args)
{
Func<object,ArgumentException> fn1 = null;

Func<string, Exception> fn2 = null;
fn2 = fn1; //Covariance and Contravariance
}

}

كما ترى في المثال السابق  قمنا بتعريف مفوض من نوع (Func) لديه الإسم (fn1) يقبل حقل من نوع (object) ويعيد قيمة من نوع (ArgumentException) بعد ذلك قمنا بتعريف مفوض أخر من (Func) لديه الأسم (Fn2) يقبل حقل من نوع (string) ويعيد قيمة من نوع (Exception) بعد ذلك قمنا بإسناد (fn1) إلى (fn2) وكما تلاحظ فإن الحقل الأول من (fn1) هو منوع (object) وهو أقل إشتقاقا من (string) وأن الحقل الثاني هو من نوع (ArgumentException) وهو أكثر إشتقاقا من (Exception)

ثانيا مع Generic Interface
طبعا Generic interface تأخذ نفس مفهوم المفوضات (Delegates) حيث بإمكانك أن تعود بقيم أكثر إشتقاقا وترسل قيم أقل إشتقاقا
أنظر الى المثال التالي

public IEnumerable<Exception> GetAllException()
{
IEnumerable<ArgumentException> c=null;
return c;
}

كماترى من المثال السابق فإن القيمة التي سيتم إرجاعها من الدالة (GetAllException) هي من نوع (IEnumerable<Exception>) ولكن في الحقيقة مايتم إرجاعه من الدالة هو من نوع (IEnumerable<ArgumentException>) وهو نوع أكثر إشتقاقا من النوع الذي من المفترض أن يعيده أنظر معي الى الصورة التالية التي سوف توضح لك كل شيء إن شاء الله

كما ترى في الاعلى لدينا فصيلة (Class) من نوع عربة وفصيلة أخرى مشتقة من نوع عربة وهي سيارة (Cars) وفصيلة أخرى مشتقة من فصيلة سيارة وهي من نوع سيارة رياضية (Sport Cars) وكما ترى فكما نزلت الى الاسفل فهذا يعتبر اكثر إشتقاقا وكلما صعدت الى الاعلى فهذا يعتبر أقل إشتقاقا وهذا هو مبدء Covariance & Contravariance

الخلاصة
قمت في هذا الدرس بشرح مفهوم Covariance & Contravariance وكيف يمكن إستخدامه والنطاق الذي يستخدم فيه وحقيقة الأمر ان إطار عمل دوت نت (.Net FrameWork) يدعم هذه الميزة في جميع مفوضاته (Generics Delegate) وجميع واجهاته ( Genrics interface) وبإمكانك أيضا أن تستخدمها في الاكواد التي تكتبها والتي تتعامل بوجه التحديد مع (Generics) وبهذا الدرس أنهي سلسلة الدروس التي قدمتها عن المميزات الجديدة في لغة (C#4.0)
أتمنى أن أكون قد وفقت في الطرح
والله أعلم

 
1 Comment

Posted by on May 19, 2010 in C#

 

Tags: , , , , , , ,

المميزات الجديدة في لغة Optional Parameters and Named Arguments – C# 4.0


أولا : الحقول الإختيارية (Optional Parameters)

تعتبر ميزة البراميترات الاختيارية او ( Optional Parameters) غير جديدة على مبرمجي الفيجوال بيسك حيث تعطيك هذه الميزة حرية الاختيار بين أرسال قيمة الى البراميترات او عدم إرسال قيمة وبذلك يتم أخذ القيمة الافتراضية التي تم تحديدها مسبقا عند إنشاء الدالة (Method) لن أطيل عليكم سوف أبدء مباشرة باعطاء أمثلة عنها
كيف يمكن إنشاء براميترات إختيارية (Optional Parameter)
يتم إنشاء الحقول او البراميترات الإختيارية كما هو موضح في الشكل التالي

كما ترى وبكل بساطة فان الحقل الإختياري يجب أن يأتي بعده مباشرة قيمة إفتراضية وبذلك تخبر المترجم (Compiler) بأن هذا الحقل حقل إختياري كما هو موضح في الصورة التالية

كما ترى فإن البراميترات أو الحقول الإختيارية يتم وضعها بين علامتي [] وذلك لدلالة على أنها حقول إختيارية .

المثال كامل

class Program
{
static void Main(string[] args)
{
Add(10);
Add(10, 5);
Add(10,5,5);
}
static void Add(int A, int B = 0,int C=1)
{
Console.WriteLine("The Value Of A={0},B={1},C{2}", A, B,C);
}

ثانيا : الحقول ذات الاسماء المعلنة (Named Arguments)

في الحقيقة أرهقني مصطلح (Named Arguments)    من ناحية التعريب ولذلك أطلقت عليه إسم الحقول ذات الأسماء المعلنة. والغرض منها يكمن في إمكانية إعلان إسم الحقل الإختياري وتحديد قيمته بغض النظر عن موقعه في الدالة.
في الشفرة السابقة يوجد هنالك حقلان إختياريان الأول إسمه (B)  والثاني إسمه (C)  والان لنفترض اني اريد ان أرسل قيمة (C) فقط بدون إرسال قيمة (B) هل هذا ممكن ؟
طبعا هذا ممكن مع (Named Arguments) إنظر الى الشكل التالي

كما ترى فإن العملية بسيطة جدا كل ماعليك فعله هو تحديد إسم الحقل الذي قمت بتعريفه في الدالة ثم إرسالة القمية التي تريدها
أمثلة أخرى

وكما هو موضح في الاعلي فإن موقع الحقل لايهم في حالة ( Named Arguments)
الان تخيل معي ان لديك دالة (Method) يوجد بها أكثر من حقل إختياري ولنقل على سبيل المثال عشرة حقول إختيارية وأنك في بعض الأجزاء من الكود تريد أن ترسل قيمة الحقل  الاخير فقط او انك تريد إرسال قيمة حقلين فقط من العشرة وهكذا ؟؟؟
طبعا بدون وجود ميزة (Named Arguments) فسوف تظطر الى كتابة جميع الحقول ولكن من حسن حظنا فان هذه الميزة موجودة في لغة السي شارب (C#).

قواعد يجب أن تتبع

•    يجب أن تكتب الحقول الإختيارية بعد الحقول الأجبارية (Required Parameters) والعكس غير مقبول والا فإن المترجم سوف يظهر رسالة خطأ تخبرك بان الحقول الإختيارية يجب ان تظهر بعد الحقول الإجبارية.
•    لاتقم أبدا أبدا بتغير أسماء الحقول الإختيارية بعد إستدعائك لهذه الدالة عند إستخدام (Named Arguments ) والسبب في ذلك أن المترجم سوف يظهر رسالة خطأ مفادها بأن إسم الحقل غير موجود وتخيل معي المعاناة لو أنك قمت بإستدعاء هذه الدالة في أمكان كثيرة  من برنامجك لأنك سوف تطظر الىتغيره في كل مكان إستدعاء.


•    لايمكن إستخدام (Named Arguments) الى إذا كان هنالك ( Optional Parameters)

نقطة اخيرة

قد يسئل البعض ويقول لقد ذكرت في هذا الموضوع كلمة ( Parameters) بعد ذلك قمت بذكر كلمة (Arguments) إذا مالفرق بينهما
جواب هذا السؤال في الصورة التي بالأسفل


خلاصة
أتمنى في نهاية الحديث أن تكون الصورة واضحة لدى الجميع عن هذه الميزة الجديدة في لغة السي شارب وهي الحقول الإختيارية وطبعا كما ذكرت سابقا هي ليست بجديدة على مبرمجين الفيجوال بيسك ولكن الجديد هنا هو الحقول ذات الاسماء المعلنة وقمت بإعطائك بعض القواعد الهامة التي يجب أن تكون في الحسبان اثناء البرمجة والفرق بين كلمتي (Parameters) و ( Arguments) .
واخير وليس أخرا اتمنى ان اكون قد وفقت في الطرح
والله أعلم

 
1 Comment

Posted by on May 10, 2010 in C#

 

Tags: , , ,

المميزات الجديدة في لغة dynamic keyword – C# 4.0 الجزء الثاني


بسم الله الرحمن الرحيم

سوف اكمل في هذه المقالة الحديث عن (dynamic Keyword) والتي قمت بتعريفها سابقا في الجزء الاول فلنبدء على بركة الله بشرح القيمة الحقيقة وراء هذه الاضافة الجديدة .

لنفرض مثلا ان لديك دالة (Method) إسمها GetCalculatorهذه الدالة تقوم بارجاع فصيلة (Class) من نوع  حاسبة (Calculator) تحتوي على دالة إسمها (Add) هذه الدالة تقوم بارجاع الناتج من جمع رقمين كالتالي

Calculator calc = GetCalculator();
int sum = calc.Add(10, 20);

طبعا المثال السابق بسيط جدا ولكن لنفترض الان ان الدالة (GetCalculator) تقوم بارجاع نوع غير معروف بالنسبة اليك او ان المترجم (Compiler) لايستطيع التعرف على النوع الحقيقي فمالذي يمكن فعله في هذه الحالة ؟

طبعا الجواب بسيط وهو باستخدام دوال الانعكاس (Reflections) كما هو موضح في

المثال التالي

object calc = GetCalculator();
Type calcType = calc.GetType();
object res = calcType.InvokeMember("Add", BindingFlags.InvokeMethod, null,calc, new object[] { 10, 20 });
int sum = Convert.ToInt32(res);

ملاحظة: هذه الاشياء تواجهك اذا كانت تتعامل مع مكتبات (COM).

من المثال السابق يتضح لنا مدى صعوبة التعامل مع دوال الانعكاس وصعوبة قراءة الشفرات المكتوبة.

الكلام جميل ولكن ماعلاقة كل ماسبق ذكره بكلمة ديناميك (dynamic keyword)

حسنا انظر معي الى المثال التالي وكيف يمكن إعادة ماكتبناه في السابق مرة أخرى باستخدام (dynamic keyword)

dynamic calc = GetCalculator();
int sum = calc.Add(10, 20);

كما ترى في المثال السابق قمنا بنفس العمل الذي قمنا به باستخدام دوال الانعكاس

ولكن هذه المرة باستخدام (dynamic keyword) وكما ترى فانها تشبه لحد كبير المثال الاول ولكن الفرق اننا قمنا فط بوضع كلمة (dynamic) كنوع للمتغير.

كما هو موضح في الاعلى فإن التعرف على العملية سوف يتم وقت التنفيذ (Runtime)

اتمنى مما قدمته حتى الان ان تكون الصورة واضحة اليك .تخيل معي الان أنك تريد انشاء فصيلة (Class) وتريد إضافة حقول اليها ولكن وقت التنفيذ ؟؟؟

طبعا يمكنك فعل ذلك الان وبكل بساطة إنظر الى المثال التالي

dynamic contact = new ExpandoObject();
contact.Name = "Ahmed Naji";
contact.WebSite="www.dotnetfinder.wordpress.com";
Salary=1000;
Console.WritLine(contact.Name);
Console.WriteLine(contact.WebSite);

طبعا الغرض من هذه الإضافة حقا هو السهولة والبساطة في كتابة الشفرات وإعطاء قابلية كبيرة بأن تكون شفراتك أكثر مرونة.

والان سوف اتحدث عن جانب اخر مهم جدا جدا .لنفترض ان لدينا شفرة (Code) مكتوب بلغة من اللغات الديناميكة وأن هذه اللغة هي (IronPython) كما هو موضح بالأسفل

واننا نريد ان نستدعى الدالة (function) الموجودة في كود (IronPython) من خلال لغة سي شارب .هل هذا ممكن؟

والاجابة ايضا بسيطة وهي باستخدام (dynamic keyword) إنظر الى المثال التالي

مدهش بلا شك لقد قمنا بتنفيذ كود مكتوب بلفة (IronPython) داخل لغة سي شارب بكل يسر وسهولة .والان سوف ياتي سؤال مهم جدا كيف تم تنفيذ شفرة مكتوبة بلغة (IronPython) داخل شفرة مكتوبة بلغة سي شارب ؟؟؟

لكي إجيبكم على هذا السؤال أنظروا الى الصورة  بالاسفل.

كما ترى في المثال السابق فان اللغات مسبقة التعريف (Statically_Typed) تتخاطب مباشرة مع لغة التنفيذ المشتركة (CLR) ولكن الحال مختلف مع اللغات الديناميكية مثل (IronPython) فيوجد هنالك لغة التنفيذ الديناميكية (DLR) والتي تقوم بدورها بالتخاطب مع (CLR) ونفس الشيء ينطبق عندما تقوم بتنفيذ شفرات مكتوب بلغات ديناميكية داخل لغة سي شارب .

وكما ترى مماسبق فان لغة التنفيذ الديناميكية(DLR) تلعب هنا دور الوسيط بين لغة التنفيذ المشتركة (CLR) وبين اللغات الديناميكة من جهة وبين لغة السي شارب واللغات الديناميكية من جهة أخرى.

طبعا هنالك حالات اخرى فيمكن ان تقوم بتنفيذ ملف مكتوب بلغة الجافا سكريبت (JavaScript) داخل تطبيقات سيلفر لايت (Silverlight).

الرؤية التي تطمح اليه مايكروسوفت

قد يسئل البعض مالغرض الاساسي والرؤية التي تريدها شركة مايكروسوفت .

اولا قابلية التعدد

فيمكن ان يكون في المشروع الواحد مبرمجين بلغة السي شارب ومبرمجين بلغة (IronPython) ومبرمجين جافا سكريبت (JavaScript)

ثانيا جذب أنظار المبرمجين والمطورين من لغات مختلفة نحو منصة عمل دوت نت (.Net Framework) واستخدام المنتجات المختلفة مثل (Visual Studio)

ثالثا السهولة في التعامل مع مكتبات (Com) وخاصة المتعلقة بتطبيقات أوفيس

س/ هل معنى هذا الكلام ان لغة سي شارب سوف تصبح لغة ديناميكية؟؟؟

طبعا لا فالغة سي شارب لغة مسبقة التعاريف ولكن ان تسلك سلوك اللغات الديناميكية فهذا من أجل تسهيل العمليات ولجعل الامور اسهل فكما راينا الفرق الواضح عند استخدام دوال الانعكاس وعند استخدام (dynamic keyword).وايضا سهولة تنفيذ شفرات اخرى من لغات ديناميكية داخل لغة سي شارب.

الخلاصة

أتمنى من جميع مماسبق من شرح في الجزء الأول والثاني أن كون قد أعطيتكم لمحة كافية عن الميزة الهامة جدا في لغة السي شارب وكيف يمكن كتابتها وكيف يمكن إستخدامها وكيف يمكن تنفيذ لغات ديناميكية من داخل لغة سي شارب والفرق عند إستخدام دوال الإنعكاس واستخدام كلمة ديناميك والأهداف التي تسعى اليها شركة مايكروسوفت .

والله أعلم

 
Leave a comment

Posted by on May 1, 2010 in C#

 
 
Follow

Get every new post delivered to your Inbox.