PDA

View Full Version : مقاله: همه چی در مورد dynamic در c#



r00tkit
یک شنبه 12 اردیبهشت 1389, 18:33 عصر
سلام قصد دارم در مورد نوع dynamic در سی شارپ کمی بنویسم:خجالت: (اگه اشکال داشت که داره :افسرده:به بزرگی خودتون ببخشید:بوس:)
اگه دوستان استقبال کنند ادامه می دم:قلب:


C#‎‎‎‎‎ یه زبان برنامه نویسی type-safe هستش یعنی همه عبارات به یک نمونه از یک تایپ تبدیل شده و کامپایلر فقط کدی رو تولید می کنه که در حال انجام کاری باشه که برای ان تایپ خاص معتر باشه .سود زبان های type-safe بر زبان های non-type-safe این است که اکثر اشکالات برنامه نویس در زمان کامپایل مشخص شده،و این باعث می شه از درست بودن کد قبل از تلاش برای اجرا مطمئن باشیم.

زبان های زمان کامپایل معمولا کد های سریع و کوچک تری درست می کنند به این خاطر که در زمان کامپایل کامپایلر اطلاعات بیشتری درست و به IL وmetadata تبدیل می کنه

با این وجود بعضی مواقع هستش که برنامه می خواد بر روی اطلاعاتی کار کنه که فقط در زمان اجرا در دست رس هستش

زمانی که شما از زبان های type-safe استفاده می کنید(مثل C#‎‎‎‎‎) برای انجام فعل انفعال بر روی این چنین اطلاعاتی (همون هایی که تو زمان اجرا معلوم می شدن) سینتکس بد جوری زمخت‌ می شه مخصوصا" وقتی با string ها ی زیاد کار می کنید و کارایی افت می کنه. در سی شارپ این اتفاق زمانی رخ می ده که شما دارید با reflection کار می کنید.

با این وجود بعضی از developer ها از C#‎‎‎‎‎ استفاده می کنن برای ارتباط با componet هایی که در C#‎‎‎‎‎ پیاده سازی نشده اند بعضی از این ها می تونه زبان های dynamic تحت .net باشه مثل Ruby و Python یا اشیای COM که از اینترفیس IDispatch پشتیبانی می کنند(که ممکن هستش در native c/C++‎‎‎‎‎ پیاده سازی شده باشند) یا اشیای DOM(HTML Document Object Model)( که با زبان/ تکنولوژِی های مختلف پیاده سازی می شن) استفاده از اشياء HTML DOM مخصوصا" در ساخت برنامه های Silverlight مفید هستش.
----------------
برای اسان کردن کار developer هایی که از reflection استفاده می کنن برای کار با component دیگه، کامپایلر C#‎‎‎‎‎ یه راهی رو پیشنهاد می ده برای mark کردن نوع عبارات به dynamic ، شما حتی می تونین نیجه ی عبارات رو داخل متغیر هایی از نوع dynamic قرار بدین

dynamic expression/variable می تونه سپس استفاده بشه برای invoke کردن اعضاء عضو مثل field,
property/indexer, method, delegate, unary/binary/conversion operators

زمانی که کد شما در عبارات یا متغیر های dynamic عضوی رو فراخوانی می کنه کامپایلر کد خاص IL لی رو تولید می کنه که ان عمل رو تشریح می کنه. که این کد به اسم payload شناخته می شه. در زمان اجرا payload نوع دقیق عمل رو برای اجرا مبني‌ بر نوع واقعی object که حالا به عنوان dynamic expression/variable شناخته می شه

نگاه کنید:


Private static class DynamicDemo {
public static void Main() {
for (Int32 demo = 0; demo < 2; demo++) {
dynamic arg = (demo == 0) ? (dynamic) 5 : (dynamic) "A";
dynamic result = Plus(arg);
M(result);
}
}

static dynamic Plus(dynamic arg) { return arg + arg; }

private static void M(Int32 n) { Console.WriteLine("M(Int32): " + n); }
private static void M(String s) { Console.WriteLine("M(String): " + s); }
}

خروجی :



M(Int32): 10
M(String): AA
ادامه دارد ... (خسته شدم )

-------------------
منظور ironruby و ironpython هستش

r00tkit
یک شنبه 12 اردیبهشت 1389, 23:24 عصر
دست عزیز اقای fastcode توی پیام خصوصی به من گفتن field رو نمی شه invoke کرد

درست هستش ولی منظور در این جا member access هستش

صفحه ی 149 CLR via csharp



this dynamic expression/variable can then be used to invoke a member such as a field, a
property/indexer, a method, delegate, and unary/binary/conversion operators

منظور اقای Jeffrey Richter این بود




member access (method call, field, property, or indexer access, or a delegate invocation) or application of an operator on a value of such type is permitted without any type checking, and its resolution is postponed until run-time

r00tkit
دوشنبه 13 اردیبهشت 1389, 17:04 عصر
سلام
خوشحالم که استقبال شد:قلب:
امروز حالم کمی خوب هستش:قهقهه:(50 % قضیه حلّه:خجالت:)
در مورد


‎‎‎‎‎‎ C#‎ یه زبان برنامه نویسی type-safe هستش یعنی همه عبارات به یک نمونه از یک تایپ تبدیل شده و ...
static language رو اضاقه کنید

خوب بریم به اصل ماجرا:

برای متوجه شدن این که چی اتفاقی افتاد از متود Plus شروع می کنیم این متود نوع پارامتر هاشو رو dynamic بیان کرده و در داخل متود اراگومان ها در داخل یه + دوگانی(باینری)به عنوان عملوند استفاده می شن ، از Arc داینامیک هستش کامپایلر C#‎ یه payloadدی رو درست(ساتع ,emit) می کنه که ان در زمان اجرا نوع دقیق arc رو و واقعا" عملگر + چه چیزی رو باید انجام بده رو مشخص می کنه .
اولین باری که Plus فراخوانی می شه 5 ( یه Int32 ) پاس می شه بنا بر این Plus عدد 10 رو (بازم یه Int32) رو به فراخواننده بر می گردونه ،که این مقدار بازگشتی داخل متغیر result قرار می گیره (که نوع اش dynamicهستش) سپس متود M فراخوانی می شه ،برای فرا خوانی M کامپایلر Payload رو درست می کنه که در زمان اجرا نوع دقیق مقداری که به توابع فرستاده شده و کدوم overload دی رو که باید اجرا شه رو مشخص می کنه،
وقتی که result شامل Int32 هستش ان overloadدی از M اجرا می شه که نوع Int32 رو به عنوان پارامتر قبول می کنه.

دومین دفعه که Plus فراخوانی می شه، "A" (یه String) پاس می شه بنا بر این Plus به عنوان بازگشت "AA" رو بر می گردونه که مثل دفعه ی قبل نتیجه داخل متغییر Result قرار می گیره بازم M فرا خوانی می شه تو این دفعه payload نوع ورودی رو String و overload دی که اجرا می شه همونی می شه که String روبه عنوان پارامتر قبول می کنه.
وقتی که یه فیلد ،پارامتر های ورودی توابع و نوع باز گشتی از توابع و یا متغیر های محلی نوعش dynamic می شه کامپایلر این نوع(type)رو به System.Object تبدیل می کنه و اتریبیوت System.Runtime.CompilerService.DynamicAttribute رو به metadata آی ان(نوع بازگشتی،پارامتر،فیلد) اعمال می کنه واگه متغیر های محلی نوعشوت dynamic باشه سپس بارم نوعشون Object می شه اما دیگه DynamicAttribute دیگه بهش اعمال نمی شه.
این یه نکته داره که بعدا" می گم

dynamic و Object واقعا" یکی هستنند شما نمی تونید متودی بنویسید که امضاء شون فقط در dynamic یا Object بودت فرق کنه

حتی این امکان هم هست که از dynamic در موقع مشخص کردن آرگومان های نوع ها
( type arguments)در جنریک ها استفاده کنیم
(a structure (value type), an interface, a delegate, or a method ,class)
مثال:


static class DynamicDemo
{
static T myfunction<T>(T x)
{
return x;
}

public static void Main()
{
Console.WriteLine(myfunction<dynamic>(4));

}
}

وقتی این کار رو انجام می دین کامپایلر نوع رو به Object تبدیل کرده و DynamicAttribute رو قسمت هایی از metadata که نیاز هستش applie می کنه
وقتی که شما با جنریک ها کار می کنید این کد ها کامپایل شده و و نوع ها Object در نظر گرفته می شود و چیزی اضافی در زمان اجرا انجام نمی شه چون کامپایلر هیچ payloadدی برای generic ها تولید نمی کنه
هر expression نی می تونه به صورت Implicit به داینامیک cast بشه چون که همه نتایج عبارات از Object مشتق‌ می شن( ولیو تایپ ها box می شن )
به صورت معمولی کامپایلر به شما اجازه نمی ده کدی بنویسید که به صورت implicitly یه عبارتی رو از Object به یه نوع دیگه cast کنین باید این کار رو با explicit cast انجام بدین
با این وجود شما می تونین از dynamic به هر نوعی به صورت Implicit cast کنید



Object o1 = 123; // OK: Implicit cast from Int32 to Object (boxing)
Int32 n1 = o; // Error: No implicit cast from Object to Int32
Int32 n2 = (Int32) o; // OK: Explicit cast from Object to Int32 (unboxing)

dynamic d1 = 123; // OK: Implicit cast from Int32 to dynamic (boxing)
Int32 n3 = d; // OK: Implicit cast from dynamic to Int32 (unboxing)
اگه کد در زمان اجرا نتونه cast بشه باید منتظر InvalidCastException باشید

r00tkit
یک شنبه 19 اردیبهشت 1389, 22:24 عصر
بازم سلام

بی مقدمه ادامه میدم



dynamic r = 5;
var t =M( r);
Console.WriteLine(t.


اگه اینجا دیگه IntelliSense کار نمی کنه چون نوع t هم داینامیک هستش ،در زمان اجرا معلوم می شه نوع t چی هستش و کدوم M اجرا می شه

نکته: اگه M نوع برگشتیش void بود هیچ exception رخ نمی ده عوضش null بر می گرده

مهم : var رو با dynamic قاطی نکنید
var در متغیر های محلی استفاده می شه برای کوتاه کردن code هستش و کامپایلر نوع رو از عبارت تشخیص می ده

var فقط به عنوان local variable استفاده میشه در شما نمی تونین چیزی cast کنید به var ولی به dynamic میشه
یه فرق دیگه اینکه شما در هنگام تعریف متغییر از نوع var حتما" باید مقدار دهیش کنید در صورتی که در dynamic نیازی نیست
اگه این کار رو نکنید این خطا رو می گیره



Implicitly-typed local variables must be initialized


با توجه به


dynamic d = 123;
var x = (Int32) d; // Conversion: 'var x' is the same as 'Int32 x'
var dt = new DateTime(d); // Construction: 'var dt' is the same as 'DateTime dt'


نوع x از داینامیک به static تبدیل می شه یعنی همون int32
و dt هم همین جور

یه سری مطلب دیگه هم هست در مورد dynamifcation و استفاده از dynamic ها به جای reflection برای اسان سازی کد نوشتن که فقط مثال می زنم
که دیگه حوصلم نمی یاد توضیح بدم (اگه کسی خواست بگه بنویسم)

مثال dynamifcation



public static void Main() {
Application excel = new Application();
excel.Visible = true;
excel.Workbooks.Add(Type.Missing);
((Range)excel.Cells[1, 1]).Value = "Text in cell A1";
}


با dynamifcation




public static void Main() {
Application excel = new Application();
excel.Visible = true;
excel.Workbooks.Add(Type.Missing);
excel.Cells[1, 1].Value = "Text in cell A1";
}

مثال 2


Object target = "Jeffrey Richter";
Object arg = "ff";

// Find a method on the target that matches the desired argument types
Type[] argTypes = newType[] { arg.GetType() };
MethodInfo method = target.GetType().GetMethod("Contains", argTypes);

// Invoke the method on the target passing the desired arguments
Object[] arguments = newObject[] { arg };
Boolean result = Convert.ToBoolean(method.Invoke(target, arguments));


با dynamic دیگه نیازی به این همه کار نیست



dynamic target = "Jeffrey Richter";
dynamic arg = "ff";
Boolean result = target.Contains(arg);