Forwarded from DotNetZoom (محمد جواد ابراهیمی)
❇️ ساخت دیتابیس یکبار مصرف Mongo بدون نیاز به نصب آن!
کتابخانه Mongo2Go یه کتابخونه عالی برای Integration Testing پروژه هایی هست که از MongoDb استفاده میکنند
🔶 توسط این کتابخونه می تونین دیتابیس های MongoDb رو بدون نیاز به نصب اون به صورت یکبار مصرف ایجاد کنین، یعنی یه دیتابیس موقت (توی پوشه Temp سیستم عامل) براتون میسازه و در آخر وقتی کارتون باهاش تموم شد اون رو حذف میکنه. در نتیجه برای Integration Testing بسیار مناسب و کاربردی هست.
🔷 قاعدتا برای استفاده از مونگو باید ورژن متناسب با سیستم عاملتون رو نصب و کانفیگ کنین یا راحت تر اینکه اون رو توسط Docker راه اندازی کنین ولی توسط این کتابخونه دیگه نیازی به نصب اون ندارین چون فایل های باینری MonogDb رو داخل خودش داره (واسه همین یه مقدار حجمش زیاده، 69 مگابایت)
🔰طرز کار باهاش خیلی سادس فقط کافیه ناگتش رو نصب کنین
https://github.com/Mongo2Go/Mongo2Go
_________________
@DotNetZoom
کتابخانه Mongo2Go یه کتابخونه عالی برای Integration Testing پروژه هایی هست که از MongoDb استفاده میکنند
🔶 توسط این کتابخونه می تونین دیتابیس های MongoDb رو بدون نیاز به نصب اون به صورت یکبار مصرف ایجاد کنین، یعنی یه دیتابیس موقت (توی پوشه Temp سیستم عامل) براتون میسازه و در آخر وقتی کارتون باهاش تموم شد اون رو حذف میکنه. در نتیجه برای Integration Testing بسیار مناسب و کاربردی هست.
🔷 قاعدتا برای استفاده از مونگو باید ورژن متناسب با سیستم عاملتون رو نصب و کانفیگ کنین یا راحت تر اینکه اون رو توسط Docker راه اندازی کنین ولی توسط این کتابخونه دیگه نیازی به نصب اون ندارین چون فایل های باینری MonogDb رو داخل خودش داره (واسه همین یه مقدار حجمش زیاده، 69 مگابایت)
🔰طرز کار باهاش خیلی سادس فقط کافیه ناگتش رو نصب کنین
Install-Package Mongo2Go
و به صورت زیر ازش استفاده کنینusing (var runner = MongoDbRunner.Start())ریپازیتوری گیتهاب :
{
var client = new MongoClient(runner.ConnectionString);
var database = client.GetDatabase("IntegrationTest");
var collection = database.GetCollection<TestDocument>("TestCollection");
//Just use it!
}
https://github.com/Mongo2Go/Mongo2Go
_________________
@DotNetZoom
GitHub
GitHub - Mongo2Go/Mongo2Go: Mongo2Go - MongoDB for .NET integration tests
Mongo2Go - MongoDB for .NET integration tests. Contribute to Mongo2Go/Mongo2Go development by creating an account on GitHub.
Forwarded from کدهک
freetalk
فری تاک
🔰گپ و گفت خودمونی و فان
توی این قسمت از #فری_تاک، من و حکیم و معین یه گپ و گفت خودنی و فان داریم
از سوتی هامون توی برنامه نویسی میگیم و ضرر هایی که بالا آوردیم
از تجربه های شکست و موفقیت هامون حرف میزنیم و...
و میگیم و میخندیم و شوخی میکنیم
این قسمت اولین قسمت از این سبک جدید هست که گپ و گفت های خودمونی و فان داریم.
گوش که دادین حتما فیدبک بدین که اگه دوس داشتین بیشتر از اینا بذاریم.
همیشه قرار نیس بحث فنی بکنیم، یه وقتایی هم لازمه بگیم و بخندیم و حال دلمون رو خوب کنیم. (این وسط یه تجربیاتی هم رد و بدل میکنیم)
خوش باشین :)
_________________
@DotNetZoom
توی این قسمت از #فری_تاک، من و حکیم و معین یه گپ و گفت خودنی و فان داریم
از سوتی هامون توی برنامه نویسی میگیم و ضرر هایی که بالا آوردیم
از تجربه های شکست و موفقیت هامون حرف میزنیم و...
و میگیم و میخندیم و شوخی میکنیم
این قسمت اولین قسمت از این سبک جدید هست که گپ و گفت های خودمونی و فان داریم.
گوش که دادین حتما فیدبک بدین که اگه دوس داشتین بیشتر از اینا بذاریم.
همیشه قرار نیس بحث فنی بکنیم، یه وقتایی هم لازمه بگیم و بخندیم و حال دلمون رو خوب کنیم. (این وسط یه تجربیاتی هم رد و بدل میکنیم)
خوش باشین :)
_________________
@DotNetZoom
🔰گپ و گفت خودمونی و فان
توی این قسمت از #فری_تاک، من و حکیم و معین یه گپ و گفت خودنی و فان داریم
از سوتی هامون توی برنامه نویسی میگیم و ضرر هایی که بالا آوردیم
از تجربه های شکست و موفقیت هامون حرف میزنیم و...
و میگیم و میخندیم و شوخی میکنیم
این قسمت اولین قسمت از این سبک جدید هست که گپ و گفت های خودمونی و فان داریم.
گوش که دادین حتما فیدبک بدین که اگه دوس داشتین بیشتر از اینا بذاریم.
همیشه قرار نیس بحث فنی بکنیم، یه وقتایی هم لازمه بگیم و بخندیم و حال دلمون رو خوب کنیم. (این وسط یه تجربیاتی هم رد و بدل میکنیم)
خوش باشین :)
لینک ویس ضبط شده:
https://t.me/DotNetZoom/1236
_________________
@DotNetZoom
توی این قسمت از #فری_تاک، من و حکیم و معین یه گپ و گفت خودنی و فان داریم
از سوتی هامون توی برنامه نویسی میگیم و ضرر هایی که بالا آوردیم
از تجربه های شکست و موفقیت هامون حرف میزنیم و...
و میگیم و میخندیم و شوخی میکنیم
این قسمت اولین قسمت از این سبک جدید هست که گپ و گفت های خودمونی و فان داریم.
گوش که دادین حتما فیدبک بدین که اگه دوس داشتین بیشتر از اینا بذاریم.
همیشه قرار نیس بحث فنی بکنیم، یه وقتایی هم لازمه بگیم و بخندیم و حال دلمون رو خوب کنیم. (این وسط یه تجربیاتی هم رد و بدل میکنیم)
خوش باشین :)
لینک ویس ضبط شده:
https://t.me/DotNetZoom/1236
_________________
@DotNetZoom
Forwarded from کدهک
✅ آموزش Unit Testing با استفاده از NUnit و Moq بخش دوم: Mocking
در زمینه Unit Testing گاهی اوقات یک Unit یا کلاس وابستگی هایی دارد که مورد بررسی برای تست نیستند. همچنین Unit مورد نظر بدون داشتن این وابستگی ها نمیتواند کار کند. یکی از راه های حل این مشکل، شبیه سازی وابستگی های Unit یا کلاس است که به Mocking معروف می باشد. یکی از کتابخانه های بسیار کاربردی و معروف در زمینه Mocking ، کتابخانه Moq می باشد که در این مقاله قصد داریم به بررسی آن بپردازیم
#بابک_طارمی
https://vrgl.ir/BnMoW
_____________
@DotNetZoom
در زمینه Unit Testing گاهی اوقات یک Unit یا کلاس وابستگی هایی دارد که مورد بررسی برای تست نیستند. همچنین Unit مورد نظر بدون داشتن این وابستگی ها نمیتواند کار کند. یکی از راه های حل این مشکل، شبیه سازی وابستگی های Unit یا کلاس است که به Mocking معروف می باشد. یکی از کتابخانه های بسیار کاربردی و معروف در زمینه Mocking ، کتابخانه Moq می باشد که در این مقاله قصد داریم به بررسی آن بپردازیم
#بابک_طارمی
https://vrgl.ir/BnMoW
_____________
@DotNetZoom
ویرگول
آموزش Unit Testing با استفاده از NUnit و Moq بخش دوم: Mocking
در این مقاله قصد داریم که به Mocking و کتابخانه محبوب Moq بپردازیم
🔰 الان داشتم اینو سرچ میکردم میزارم اینجا هم آرشیو بشه هم شاید به دردتون بخوره
واسه Encode کردن URL راه های مختلفی تو دات نت وجود داره
HttpUtility.UrlPathEncode
HttpUtility.UrlEncode
WebUtility.UrlEncode
Uri.EscapeUriString
Uri.EscapeDataString
🔸داغون ترینشون اینه HttpUtility.UrlPathEncode
اصلا درست کار نمیکنه و خروجی رو خراب میکنه تو بعضی موارد. مثلا % و # رو encode نمیکنه
اینجا یه سری مواردش رو گفته
https://stackoverflow.com/a/1148326
🔹اینم یه سری مشکلات داره Uri.EscapeUriString و جدیدا deprecate شده
تو یه سری موارد خروجی رو خراب میکنه مثلا # رو encode نمیکنه
توضیحات بیشتر
https://stackoverflow.com/a/34189188
🔸این 2تا مثل هم رفتار میکنن و روششون اینطوریه که space رو به "+" تبدیل میکنن. فقط یه تفاوت کوچیک دارن
WebUtility.UrlEncode (حروف UpperCase تولید میکنه)
HttpUtility.UrlEncode (حروف LowerCase تولید میکنه)
🔹این 2تا مشکلی که دارن اینه که یه سری کاراکتر های «رزرو نشده» مثل "~" رو هم encode میکنن
توضیحات بیشتر
https://stackoverflow.com/a/47877559
✅ بهترینشون هم که خروجی کاملا استاندارد تولید میکنه و هیچ کدوم از این مشکلات رو نداره اینه
Uri.EscapeDataString
توضیحات بیشتر
https://stackoverflow.com/questions/602642/server-urlencode-vs-httputility-urlencode/
____________________
@DotNetZoom
واسه Encode کردن URL راه های مختلفی تو دات نت وجود داره
HttpUtility.UrlPathEncode
HttpUtility.UrlEncode
WebUtility.UrlEncode
Uri.EscapeUriString
Uri.EscapeDataString
🔸داغون ترینشون اینه HttpUtility.UrlPathEncode
اصلا درست کار نمیکنه و خروجی رو خراب میکنه تو بعضی موارد. مثلا % و # رو encode نمیکنه
اینجا یه سری مواردش رو گفته
https://stackoverflow.com/a/1148326
🔹اینم یه سری مشکلات داره Uri.EscapeUriString و جدیدا deprecate شده
تو یه سری موارد خروجی رو خراب میکنه مثلا # رو encode نمیکنه
توضیحات بیشتر
https://stackoverflow.com/a/34189188
🔸این 2تا مثل هم رفتار میکنن و روششون اینطوریه که space رو به "+" تبدیل میکنن. فقط یه تفاوت کوچیک دارن
WebUtility.UrlEncode (حروف UpperCase تولید میکنه)
HttpUtility.UrlEncode (حروف LowerCase تولید میکنه)
🔹این 2تا مشکلی که دارن اینه که یه سری کاراکتر های «رزرو نشده» مثل "~" رو هم encode میکنن
توضیحات بیشتر
https://stackoverflow.com/a/47877559
✅ بهترینشون هم که خروجی کاملا استاندارد تولید میکنه و هیچ کدوم از این مشکلات رو نداره اینه
Uri.EscapeDataString
توضیحات بیشتر
https://stackoverflow.com/questions/602642/server-urlencode-vs-httputility-urlencode/
____________________
@DotNetZoom
Stack Overflow
Server.UrlEncode vs. HttpUtility.UrlEncode
Is there a difference between Server.UrlEncode and HttpUtility.UrlEncode?
Forwarded from کدهک
Forwarded from DotNetZoom (محمد جواد ابراهیمی)
✅ نمایش تعداد کاربران آنلاین در AspNet Core
برای محاسبه تعداد کاربران آنلاین اساسا دو روش وجود داره
1️⃣ روش اول - با استفاده از Cookie
در ASP.NET قدیم داخل کلاس global.asax متد هایی وجود داشت به نام Session_Start و Session_End که به هنگام شروع و پایان "سشن" کاربری، فراخوانی میشدن (با شی Session اشتباه گرفته نشود)
رخداد Session_Start زمانی raise یا اجرا میشد که یک سشن جدید برای یک کاربر ساخته بشه
و رخداد Session_End نیز زمانی raise میشد که یک سشن expire (منقضی) بشه
🔰مکانیزمی که سشن کاربری رو ایجاد ومنقضی میکرد، مراحلش به این صورت بود که:
▪️اولین بار که شخصی سایت رو باز میکرد، خود ASP.NET یک کوکی به نام "ASP.NET_SessionD" با مقدار یک "کلید تصادفی" به همراه Response برای کاربر میفرستاد و اون در مرورگر کاربر ذخیره میشد و از اون طرف همین "کلید تصادفی" در حافظه مموری سرور (به کمک شی Session) به عنوان شناسه یک کاربر (که شاید هنوز نمیدونیم کیه ولی میدونیم یه کاربره) ذخیره میشد (تا اینجای کار یک سشن برای کاربر جدید ساخته شده، در نتیجه رخداد Session_Start فراخوانی میشد)
▪️از درخواست های بعدی، این کوکی به همراه مقدارش (همون کلید تصادفی)، به Server ارسال میشد سپس ASP.NET این کلید رو میخوند و با مقادیر ذخیره شده در شی Session (در حافظه رم) مطابقت میداد و متوجه میشد که این همون کاربری هست که قبلا درخواست زده بود.
تایم منقضی شدن این سشن ها (session expire) به صورت پیشفرض 20 دقیقه بود و مادامی که درخواست یا بازدید از سمت همون کاربر میومد، این مدت زمان تمدید میشد.
در نتیجه مادامی که آخرین درخواست کاربر کمتر از 20 دقیقه قبل بود، سشن برقرار بود و زمانی که این مدت از 20 بیشتر میشد. اون سشن به صورت خودکار expire/منقضی میشد (در این مرحله رخداد Session_End فراخوانی میشد)
🔸بنابراین مادامی که کاربر ما، فاصله بین هر درخواستش کمتر از 20 دقیقه بود، سشن اون کاربر برقرار بود و یک کاربر "آنلاین" به حساب میومد
و زمانی که از آخرین درخواست کاربر، بیش از 20 دقیقه میگذشت، سشن کاربر منقضی شده و یک کاربر "آفلاین" به حساب میومد
در این حالت با کمی کد نویسی میشد تعداد کاربران آنلاین رو محاسبه کرد، به این صورت که یک متغیر global برای تعداد کاربران آنلاین در نظر میگرفتیم و به هنگام Session_Start اون رو ++ (یکی اضافه) و به هنگام Session_End اون رو -- (یکی کم) میکردیم
نکته: این توضیحات حالت پیشفرض هست، در صورت تنظیم sessionState میتونه محل ذخیره سازی سشن و کوکی در سمت سرور و کلاینت متفاوت باشه (مثلا ذخیره شدن سشن ها درون یک دیتابیس SqlServer به جای Memory یا تنظیم شدن کلید تصادفی درون URL به جای کوکی) - توضیحات بیشتر
🔹در ASP.NET Core اما این مکانیزم و این دو متد دیگه وجود نداره. پس مجبوریم مشابه همین مکانیزم رو خودمون کدنویسی و طراحی کنیم. کد نویسیش کار خاصی نداره، همین مراحل ساخت کوکی با یک "کلید تصادفی" (مثلا guid) و ذخیره اون علاوه بر Response، درون یک InMemory Cache داخل یک Middleware به سادگی انجام میشه
🔸در این روش چون فاصله زمانی 20 دقیقه رو برای session expire هست در نتیجه همیشه ما یک تلورانس و اختلاف 20 دقیقه ای ممکنه داشته باشیم. اگر کاربر جاری همین الان مرورگرش رو میبنده یا برق میره چون session اش تا 20 دقیقه از آخرین بازدیدش معتبر هست، همچنان تا 20 دقیقه آینده "آنلاین" محسوب میشه
2️⃣ روش دوم - با استفاده از ارتباطات Realtime مانند SignalR
🔹این روش خیلی مشابه روش قبل هست با این تفاوت که به محض برقرار شدن اتصال کاربر (رخداد OnConnectedAsync کلاس Hub) اون رو به عنوان کاربر آنلاین و به محض قطع شدن ارتباطش (رخداد OnDisconnectedAsync کلاس Hub) اون کاربر رو آفلاین در نظر میگیریم.
بقیه موارد ساخت کلید تصادفی و تنظیم کوکی جهت تشخیص کاربر از بقیه کاربر ها تقریبا مشابه قبل هست
🔸مزیت این روش اینه که دیگه ما تلورانس و اختلاف 20 دقیقه رو نخواهیم داشت و به صورت آنی و در لحظه تعداد کاربران آنلاین بروزرسانی خواهد شد
معایبش هم اینه که به دلیل استفاده از ارتباطات realtime پردازش بیشتری نسبت به روش اول روی سرور میوفته و یا اینکه امکان استفاده از ارتباطات realtime در برنامه شما به هر دلیل از جمله زیرساخت network یا محدودیت های سرور و application شما وجود نداشته باشه
🔹نکته آخر اینکه در اینجا سعی کردم مکانیزم خیلی ساده توضیح بدم اما پیاده سازی صحیح چنین مکانیزمی با توجه به امکان وقوع همزمانی مستلزم اینه که نکات پیشگیری از مشکلات همزمانی رعایت بشه
🔰در اینجا یک پروژه نمونه آماده کردم که هر دو این روش ها رو پیاده سازی کرده و میتونین با بررسی سورس کدش بیشتر با نحوه عملکرد اون آشنا بشین
https://github.com/dotnetzoom/OnlineUsers-AspNetCore
_________
@DotNetZoom
برای محاسبه تعداد کاربران آنلاین اساسا دو روش وجود داره
1️⃣ روش اول - با استفاده از Cookie
در ASP.NET قدیم داخل کلاس global.asax متد هایی وجود داشت به نام Session_Start و Session_End که به هنگام شروع و پایان "سشن" کاربری، فراخوانی میشدن (با شی Session اشتباه گرفته نشود)
رخداد Session_Start زمانی raise یا اجرا میشد که یک سشن جدید برای یک کاربر ساخته بشه
و رخداد Session_End نیز زمانی raise میشد که یک سشن expire (منقضی) بشه
🔰مکانیزمی که سشن کاربری رو ایجاد ومنقضی میکرد، مراحلش به این صورت بود که:
▪️اولین بار که شخصی سایت رو باز میکرد، خود ASP.NET یک کوکی به نام "ASP.NET_SessionD" با مقدار یک "کلید تصادفی" به همراه Response برای کاربر میفرستاد و اون در مرورگر کاربر ذخیره میشد و از اون طرف همین "کلید تصادفی" در حافظه مموری سرور (به کمک شی Session) به عنوان شناسه یک کاربر (که شاید هنوز نمیدونیم کیه ولی میدونیم یه کاربره) ذخیره میشد (تا اینجای کار یک سشن برای کاربر جدید ساخته شده، در نتیجه رخداد Session_Start فراخوانی میشد)
▪️از درخواست های بعدی، این کوکی به همراه مقدارش (همون کلید تصادفی)، به Server ارسال میشد سپس ASP.NET این کلید رو میخوند و با مقادیر ذخیره شده در شی Session (در حافظه رم) مطابقت میداد و متوجه میشد که این همون کاربری هست که قبلا درخواست زده بود.
تایم منقضی شدن این سشن ها (session expire) به صورت پیشفرض 20 دقیقه بود و مادامی که درخواست یا بازدید از سمت همون کاربر میومد، این مدت زمان تمدید میشد.
در نتیجه مادامی که آخرین درخواست کاربر کمتر از 20 دقیقه قبل بود، سشن برقرار بود و زمانی که این مدت از 20 بیشتر میشد. اون سشن به صورت خودکار expire/منقضی میشد (در این مرحله رخداد Session_End فراخوانی میشد)
🔸بنابراین مادامی که کاربر ما، فاصله بین هر درخواستش کمتر از 20 دقیقه بود، سشن اون کاربر برقرار بود و یک کاربر "آنلاین" به حساب میومد
و زمانی که از آخرین درخواست کاربر، بیش از 20 دقیقه میگذشت، سشن کاربر منقضی شده و یک کاربر "آفلاین" به حساب میومد
در این حالت با کمی کد نویسی میشد تعداد کاربران آنلاین رو محاسبه کرد، به این صورت که یک متغیر global برای تعداد کاربران آنلاین در نظر میگرفتیم و به هنگام Session_Start اون رو ++ (یکی اضافه) و به هنگام Session_End اون رو -- (یکی کم) میکردیم
نکته: این توضیحات حالت پیشفرض هست، در صورت تنظیم sessionState میتونه محل ذخیره سازی سشن و کوکی در سمت سرور و کلاینت متفاوت باشه (مثلا ذخیره شدن سشن ها درون یک دیتابیس SqlServer به جای Memory یا تنظیم شدن کلید تصادفی درون URL به جای کوکی) - توضیحات بیشتر
🔹در ASP.NET Core اما این مکانیزم و این دو متد دیگه وجود نداره. پس مجبوریم مشابه همین مکانیزم رو خودمون کدنویسی و طراحی کنیم. کد نویسیش کار خاصی نداره، همین مراحل ساخت کوکی با یک "کلید تصادفی" (مثلا guid) و ذخیره اون علاوه بر Response، درون یک InMemory Cache داخل یک Middleware به سادگی انجام میشه
🔸در این روش چون فاصله زمانی 20 دقیقه رو برای session expire هست در نتیجه همیشه ما یک تلورانس و اختلاف 20 دقیقه ای ممکنه داشته باشیم. اگر کاربر جاری همین الان مرورگرش رو میبنده یا برق میره چون session اش تا 20 دقیقه از آخرین بازدیدش معتبر هست، همچنان تا 20 دقیقه آینده "آنلاین" محسوب میشه
2️⃣ روش دوم - با استفاده از ارتباطات Realtime مانند SignalR
🔹این روش خیلی مشابه روش قبل هست با این تفاوت که به محض برقرار شدن اتصال کاربر (رخداد OnConnectedAsync کلاس Hub) اون رو به عنوان کاربر آنلاین و به محض قطع شدن ارتباطش (رخداد OnDisconnectedAsync کلاس Hub) اون کاربر رو آفلاین در نظر میگیریم.
بقیه موارد ساخت کلید تصادفی و تنظیم کوکی جهت تشخیص کاربر از بقیه کاربر ها تقریبا مشابه قبل هست
🔸مزیت این روش اینه که دیگه ما تلورانس و اختلاف 20 دقیقه رو نخواهیم داشت و به صورت آنی و در لحظه تعداد کاربران آنلاین بروزرسانی خواهد شد
معایبش هم اینه که به دلیل استفاده از ارتباطات realtime پردازش بیشتری نسبت به روش اول روی سرور میوفته و یا اینکه امکان استفاده از ارتباطات realtime در برنامه شما به هر دلیل از جمله زیرساخت network یا محدودیت های سرور و application شما وجود نداشته باشه
🔹نکته آخر اینکه در اینجا سعی کردم مکانیزم خیلی ساده توضیح بدم اما پیاده سازی صحیح چنین مکانیزمی با توجه به امکان وقوع همزمانی مستلزم اینه که نکات پیشگیری از مشکلات همزمانی رعایت بشه
🔰در اینجا یک پروژه نمونه آماده کردم که هر دو این روش ها رو پیاده سازی کرده و میتونین با بررسی سورس کدش بیشتر با نحوه عملکرد اون آشنا بشین
https://github.com/dotnetzoom/OnlineUsers-AspNetCore
_________
@DotNetZoom
Telegram
Attach Files
Forwarded from کدهک
✅ تولید تگ های SEO در ASPNET Core با کتابخانه SeoTags
تگ های زیاد و متنوعی برای بهبود SEO سایت وجود دارند. از انواع meta و link گرفته تا تگ های تنظیم Twitter Card و Open Graph تا JSON-LD و Microdata برای Structred Data تا SiteMap و...
هرکدوم هم مسلما مقادیر خاص خودشون رو میپذیرن و بسته به شرایط و نوع محتوا متفاوت هستند.
کتابخانه SeoTags تمامی تگ های مهم و کاربردی رو براحتی برای وبسایت ASPNET Core ایی شما میسازه و حالت ها و تگ های زیادی هم پشتیبانی میکنه.
اینو کتابخونه رو تازگی نوشتم (در جهت راه اندازی سایت DotNetZoom) و به زودی تکمیل ترش هم میکنم.
شما هم اگه دوست داشتین توش مشارکت کنین، issue بزنین و pull request بفرستین
طریقه استفاده و نمونه خروجی تگ ها رو میتونین توی ریپازیتوری مشاهده کنین
https://github.com/mjebrahimi/SeoTags
___________________
@DotNetZoom
تگ های زیاد و متنوعی برای بهبود SEO سایت وجود دارند. از انواع meta و link گرفته تا تگ های تنظیم Twitter Card و Open Graph تا JSON-LD و Microdata برای Structred Data تا SiteMap و...
هرکدوم هم مسلما مقادیر خاص خودشون رو میپذیرن و بسته به شرایط و نوع محتوا متفاوت هستند.
کتابخانه SeoTags تمامی تگ های مهم و کاربردی رو براحتی برای وبسایت ASPNET Core ایی شما میسازه و حالت ها و تگ های زیادی هم پشتیبانی میکنه.
اینو کتابخونه رو تازگی نوشتم (در جهت راه اندازی سایت DotNetZoom) و به زودی تکمیل ترش هم میکنم.
شما هم اگه دوست داشتین توش مشارکت کنین، issue بزنین و pull request بفرستین
طریقه استفاده و نمونه خروجی تگ ها رو میتونین توی ریپازیتوری مشاهده کنین
https://github.com/mjebrahimi/SeoTags
___________________
@DotNetZoom
GitHub
GitHub - mjebrahimi/SeoTags: 🚀 SeoTags generates All SEO Tags you need such as meta, link, Twitter card (twitter:), Open Graph…
🚀 SeoTags generates All SEO Tags you need such as meta, link, Twitter card (twitter:), Open Graph (for Facebook) (og:), and JSON-LD schema (structured data). - mjebrahimi/SeoTags
✅ تصاویر پس زمینه Windows 11
دسکتاپ تون رو صفا بدین :)
https://www.windowsobserver.com/dwnld/38638/
_____________________
@DotNetZoom
دسکتاپ تون رو صفا بدین :)
https://www.windowsobserver.com/dwnld/38638/
_____________________
@DotNetZoom
Forwarded from DotNetZoom (محمد جواد ابراهیمی)
❇️ فرق Task.Run با Task.Factory.StartNew
در این سری پست های #پرسش_پاسخ قصد دارم بعضی از سوالاتی که دوستان میپرسند رو به همراه جواب هاشون برای شما به اشتراک بگذارم
🔸سوال:
فرق Task.Run با Task.Factory.StartNew چیه؟ از کدومشون باید استفاده کنیم؟
🔹پاسخ:
خود Task.Run پشت پرده از Task.Factory.StartNew استفاده میکنه و در واقع یه Wrapper روی اون هست که استفاده ازش رو ساده تر میکنه.
علتش اینه که Task.Factory.StartNew امضا (overload) های متفاوتی داره که کار با اون رو انعطاف پذیر تر میکنه که همین انعطاف پذیری بیشتر باعث شده کار باهاش پیچیده تر باشه. مثلا وجود آپشن های بیشتری از جمله TaskCreationOptions و TaskScheduler که اجازه میده سفارشی سازی بیشتری انجام بدیم.
همچنین با توجه به اینکه خروجی متد StartNew از نوع <Task<T هست، این نوع جنریک T درواقع خروجی همون delegate ایی که بهش پاس میدین. درنتیجه اگر delegate ورودی شما به متد StartNew، خودش از نوع Task باشه، خروجی نهایی متد StartNew میشه یک <Task<Task که در این حالت بایستی توسط متد Unwarp، اون تسک داخلی (inner task) رو بیرون بکشید و با اون کار بکنید
از این رو تیم دات نت به جهت جلوگیری و مخفی کردن این پیچیدگی ها اومده Task.Run رو برای سناریو های پرکاربرد ایجاد کرده که این پیچیدگی ها رو داخل خودش مخفی میکنه
جمع بندی اینکه همیشه از Task.Run به جای Task.Factory.StartNew استفاده کنید مگر اینکه نیاز به سفارشی سازی یا استفاده از حالت های خاص دارید (اون هم با آگاهی کامل) که توضیحش از حوصله این سوال خارجه
جهت اطلاعات بیشتر مطالعه لینک زیر کمکتون میکنه
▪️Task.Run vs Task.Factory.StartNew
🔸حالا که تا اینجای کار اومدید جا داره یه نکته دیگه هم بگم
علاوه بر روش های بالا 2 روش دیگه برای ساخت یک Task وجود داره.
1- نمونه سازی تسک توسط سازنده کلاس Task
2- استفاده از کلاس TaskCompletionSource
این دو روش کمتر عمومی بوده و معمولا نیاز نمیشه از این ها استفاده کنید. روش اول بسیار کم کاربرد هست و use-case های خاصی داره و باید با احتیاط و آگاهی ازش استفاده کنین.
وقتی شما توسط Task.Run یا Task.Factory.StartNew استفاده میکنید، یک تسک برای شما ساخته میشه و بلافاصله Start میشه. درنتیحه Task ایی که به دست شما میرسه از قبل start شده و فراخوانی مجدد متد Start روی اون، باعث وقوع Exception میشه
ولی وقتی توسط سازنده کلاس Task استفاده میکنید میتونین قبل از Start شدنش به اون نمونه ایجاد شده دسترسی پیدا کنین. و سپس باید به صورت دستی متد Start رو فراخوانی کنین تا Task اجرا بشه. هرچند فراخوانی دستی متد Start بدلیل Synchronization ایی که در پشت صحنه اعمال میشه (به دلیل جلوگیری از Start شدن همزمان توسط چندین Thread) دارای سربار هست
کلاس TaskCompletionSource اما مکانیزمش کلا فرق میکنه. این کلاس وظیفه ساخت "و مدیریت" چرخه حیات یک Task رو به عهده داره.
مثلا توسط متد های SetResult و SetException و SetCanceled (و نیز همین متد ها با پشوند TryXXX به جهت مدیریت همزمانی) این امکان رو به شما میده وضعیت تسک رو به یکی از این حالات تغییر بدید:
"کنسل شده" یا "خطا رخ داده" یا "تکمیل شده با موفقیت (به همراه نتیجه خروجی اون)"
از این روش معمولا برای تبدیل کد های قدیمی APM و EAP به TPL (روش جدید تر و توصیه شده مایکروسافت) استفاده میشه و یه use-case های خاصی که باید با احتیاط و آگاهی از استفاده بشه
اطلاعات بیشتر:
▪️Mechanisms for Creating Tasks
▪️The Nature of TaskCompletionSource
▪️The danger of TaskCompletionSource class
___________________
@DotNetZoom
در این سری پست های #پرسش_پاسخ قصد دارم بعضی از سوالاتی که دوستان میپرسند رو به همراه جواب هاشون برای شما به اشتراک بگذارم
🔸سوال:
فرق Task.Run با Task.Factory.StartNew چیه؟ از کدومشون باید استفاده کنیم؟
🔹پاسخ:
خود Task.Run پشت پرده از Task.Factory.StartNew استفاده میکنه و در واقع یه Wrapper روی اون هست که استفاده ازش رو ساده تر میکنه.
علتش اینه که Task.Factory.StartNew امضا (overload) های متفاوتی داره که کار با اون رو انعطاف پذیر تر میکنه که همین انعطاف پذیری بیشتر باعث شده کار باهاش پیچیده تر باشه. مثلا وجود آپشن های بیشتری از جمله TaskCreationOptions و TaskScheduler که اجازه میده سفارشی سازی بیشتری انجام بدیم.
همچنین با توجه به اینکه خروجی متد StartNew از نوع <Task<T هست، این نوع جنریک T درواقع خروجی همون delegate ایی که بهش پاس میدین. درنتیجه اگر delegate ورودی شما به متد StartNew، خودش از نوع Task باشه، خروجی نهایی متد StartNew میشه یک <Task<Task که در این حالت بایستی توسط متد Unwarp، اون تسک داخلی (inner task) رو بیرون بکشید و با اون کار بکنید
از این رو تیم دات نت به جهت جلوگیری و مخفی کردن این پیچیدگی ها اومده Task.Run رو برای سناریو های پرکاربرد ایجاد کرده که این پیچیدگی ها رو داخل خودش مخفی میکنه
جمع بندی اینکه همیشه از Task.Run به جای Task.Factory.StartNew استفاده کنید مگر اینکه نیاز به سفارشی سازی یا استفاده از حالت های خاص دارید (اون هم با آگاهی کامل) که توضیحش از حوصله این سوال خارجه
جهت اطلاعات بیشتر مطالعه لینک زیر کمکتون میکنه
▪️Task.Run vs Task.Factory.StartNew
🔸حالا که تا اینجای کار اومدید جا داره یه نکته دیگه هم بگم
علاوه بر روش های بالا 2 روش دیگه برای ساخت یک Task وجود داره.
1- نمونه سازی تسک توسط سازنده کلاس Task
2- استفاده از کلاس TaskCompletionSource
این دو روش کمتر عمومی بوده و معمولا نیاز نمیشه از این ها استفاده کنید. روش اول بسیار کم کاربرد هست و use-case های خاصی داره و باید با احتیاط و آگاهی ازش استفاده کنین.
وقتی شما توسط Task.Run یا Task.Factory.StartNew استفاده میکنید، یک تسک برای شما ساخته میشه و بلافاصله Start میشه. درنتیحه Task ایی که به دست شما میرسه از قبل start شده و فراخوانی مجدد متد Start روی اون، باعث وقوع Exception میشه
ولی وقتی توسط سازنده کلاس Task استفاده میکنید میتونین قبل از Start شدنش به اون نمونه ایجاد شده دسترسی پیدا کنین. و سپس باید به صورت دستی متد Start رو فراخوانی کنین تا Task اجرا بشه. هرچند فراخوانی دستی متد Start بدلیل Synchronization ایی که در پشت صحنه اعمال میشه (به دلیل جلوگیری از Start شدن همزمان توسط چندین Thread) دارای سربار هست
کلاس TaskCompletionSource اما مکانیزمش کلا فرق میکنه. این کلاس وظیفه ساخت "و مدیریت" چرخه حیات یک Task رو به عهده داره.
مثلا توسط متد های SetResult و SetException و SetCanceled (و نیز همین متد ها با پشوند TryXXX به جهت مدیریت همزمانی) این امکان رو به شما میده وضعیت تسک رو به یکی از این حالات تغییر بدید:
"کنسل شده" یا "خطا رخ داده" یا "تکمیل شده با موفقیت (به همراه نتیجه خروجی اون)"
از این روش معمولا برای تبدیل کد های قدیمی APM و EAP به TPL (روش جدید تر و توصیه شده مایکروسافت) استفاده میشه و یه use-case های خاصی که باید با احتیاط و آگاهی از استفاده بشه
اطلاعات بیشتر:
▪️Mechanisms for Creating Tasks
▪️The Nature of TaskCompletionSource
▪️The danger of TaskCompletionSource class
___________________
@DotNetZoom
Microsoft News
Task.Run vs Task.Factory.StartNew
In .NET 4, Task.Factory.StartNew was the primary method for scheduling a new task. Many overloads provided for a highly configurable mechanism, enabling setting options, passing in arbitrary state, enabling cancellation, and even controlling scheduling behaviors. …
✅ گفتگو درباره Distributed Tracing در علی بابا تاک
آکادمی علیبابا، در سری برنامههای علیباباتاک، به بیان چالشها و تجربیات علیباباییها و دنیای کار میپردازه.
در این ارائه، معین تاجیک و مسعود دانشپور، درباره این موضوع صحبت خواهند کرد که چطور میتوان با استفاده از مفاهیم Open Tracing و Open Telemetry، در بین مایکروسرویسهای مختلف، درخواستهای کاربران را شناسایی و تمامی اطلاعات مفیدی که باعث بهبود روند Tracing، Debugging و شناسایی Performance Pitfall ها میشود را به وسیله پروتکلهای استاندارد و همچنین با استفاده از ابزارهای موجود در بازار جمع آوری و مانیتور کرد.
🔸زمان: سهشنبه ۲۹ تیر، ساعت ۱۷:۰۰ تا ۱۸:۳۰
🔸ثبت نام رایگان از طریق لینک زیر:
https://evnd.co/FmdPz
_________________
@DotNetZoom
آکادمی علیبابا، در سری برنامههای علیباباتاک، به بیان چالشها و تجربیات علیباباییها و دنیای کار میپردازه.
در این ارائه، معین تاجیک و مسعود دانشپور، درباره این موضوع صحبت خواهند کرد که چطور میتوان با استفاده از مفاهیم Open Tracing و Open Telemetry، در بین مایکروسرویسهای مختلف، درخواستهای کاربران را شناسایی و تمامی اطلاعات مفیدی که باعث بهبود روند Tracing، Debugging و شناسایی Performance Pitfall ها میشود را به وسیله پروتکلهای استاندارد و همچنین با استفاده از ابزارهای موجود در بازار جمع آوری و مانیتور کرد.
🔸زمان: سهشنبه ۲۹ تیر، ساعت ۱۷:۰۰ تا ۱۸:۳۰
🔸ثبت نام رایگان از طریق لینک زیر:
https://evnd.co/FmdPz
_________________
@DotNetZoom
Forwarded from DotNetZoom (محمد جواد ابراهیمی)
❇️ تفاوت Event و Delegate و مشکل نشتی حافظه (Memory Leaks) در کار با Event ها
در این پست ابتدا به تفاوت های event و delegate می پردازیم و سپس علت مشکل نشتی حافظه رو به هنگام استفاده از اون ها بررسی میکنیم (سوالی که ممکنه بعضا توی مصاحبه باهاش برخورد کرده باشین)
🔸در ابتدا باید بگم که این دو خیلی شبیه به هم هستند
1- هر دو میتونن باعث memory leak بشن
2- هر دو این امکان رو دارن که با =+ و =- بشه چندتا متد رو بهشون اضافه یا کم کرد
3- هر دو موقع raise شدن (اجرا شدن)، تمام متد های ثبت شده داخل خودشون رو فراخوانی میکنن
🔹و اما تفاوت های اونها چیه؟
در واقع event یک abstraction بر روی delegate هست که یک سری محدودیت ها (بهتره بگیم محافظت ها) رو روش اعمال میکنه
1- اجازه نمیده event رو ریست کنین (یعنی فقط اجازه میده با += و -= متدی بهش اضافه یا کم کنین ولی اجازه نمیده که با = مقدارش رو ریست کنین)
2- اون event رو فقط از طریق داخل کلاس شامل شوندش قابل فراخوانی میکنه یعنی از بیرون کسی نمیتونه اون event رو فراخوانی کنه
🔸بررسی مشکل نشتی حافظه در Event و Delegate
احتمالا خیلی جا ها دیدید یا شنیدید که میگن event ها میتونن باعث نشتی حافظه بشن. اما این مورد محدود به event نیست؛ برای delegate ها هم میتونه اتفاق بیافته. حتی برای یک شی استاتیک هم میتونه اتفاق بیافته. در واقع علت اصلی این مشکل مربوط به باقی ماندن رفرنس اشیای «بلا استفاده» هست
فرض کنین یه کلاس static داریم که داخلش یه لیست static هست. طبیعتا طول عمر این لیست به دلیل static بودن تا پایان عمر application باقی خواهد ماند، در نتیجه GC (مخفف Garbage Collector)، اون لیست رو Dispose نمیکنه
حالا اگر در طول برنامه اشیایی رو درون اون لیست Add کنیم عملا چون رفرنس اون اشیا داخل لیست باقی میمونن، اون اشیا هم تا پایان عمر برنامه Dispose نمیشن (حتی اگه دیگه با اون اشیا کاری نداشته باشیم) و همین عامل هست که باعث Memory Leak میشه
حالا مشابه همین اتفاق میتونه برای event ها و delegate ها هم بیافته
در واقع وقتی متدی از یک شی رو به یک event یا delegate (مانند Action و Func) توسط = یا =+ نسبت میدین، رفرنس اون شی هم Capture میشه، در نتیجه تا پایان عمر اون event یا delegate مربوطه، اون اشیاء هم باقی میمونن و Dispose نمیشن
🔹برای رفع این مشکل راه حل های مختلفی هست
1️⃣ استفاده از -= برای حذف کردن رفرنس (unsubscribe کردن) اون متد از event یا delegate مربوطه
2️⃣ استفاده از الگوی Weak Reference Pattern که توسط کلاس WeakEventHandler دات نت پیاده سازی میشه
3️⃣ استفاده از الگوی Event Aggregator Pattern که اون هم به نوعی از Weak Reference استفاده میکنه و داخل کتابخونه Prism زیاد ازش استفاده شده
و روش های دیگه که خارج از توضیح این پست هست
🔰جهت اطلاعات بیشتر و روش های جلوگیری از نشتی حافظه پیشنهاد میکنم مقالات زیر رو مطالعه کنین
✔️5 Techniques to avoid Memory Leaks by Events in C# .NET you should know
✔️Understanding and Avoiding Memory Leaks with Event Handlers and Event Aggregators
✔️Memory Leak in C#
✔️Are you afraid of event handlers because of C# memory leak?
✔️Events: Demystifying Common Memory Leaks
✔️Weak Event Patterns
_________________
@DotNetZoom
در این پست ابتدا به تفاوت های event و delegate می پردازیم و سپس علت مشکل نشتی حافظه رو به هنگام استفاده از اون ها بررسی میکنیم (سوالی که ممکنه بعضا توی مصاحبه باهاش برخورد کرده باشین)
🔸در ابتدا باید بگم که این دو خیلی شبیه به هم هستند
1- هر دو میتونن باعث memory leak بشن
2- هر دو این امکان رو دارن که با =+ و =- بشه چندتا متد رو بهشون اضافه یا کم کرد
3- هر دو موقع raise شدن (اجرا شدن)، تمام متد های ثبت شده داخل خودشون رو فراخوانی میکنن
🔹و اما تفاوت های اونها چیه؟
در واقع event یک abstraction بر روی delegate هست که یک سری محدودیت ها (بهتره بگیم محافظت ها) رو روش اعمال میکنه
1- اجازه نمیده event رو ریست کنین (یعنی فقط اجازه میده با += و -= متدی بهش اضافه یا کم کنین ولی اجازه نمیده که با = مقدارش رو ریست کنین)
2- اون event رو فقط از طریق داخل کلاس شامل شوندش قابل فراخوانی میکنه یعنی از بیرون کسی نمیتونه اون event رو فراخوانی کنه
🔸بررسی مشکل نشتی حافظه در Event و Delegate
احتمالا خیلی جا ها دیدید یا شنیدید که میگن event ها میتونن باعث نشتی حافظه بشن. اما این مورد محدود به event نیست؛ برای delegate ها هم میتونه اتفاق بیافته. حتی برای یک شی استاتیک هم میتونه اتفاق بیافته. در واقع علت اصلی این مشکل مربوط به باقی ماندن رفرنس اشیای «بلا استفاده» هست
فرض کنین یه کلاس static داریم که داخلش یه لیست static هست. طبیعتا طول عمر این لیست به دلیل static بودن تا پایان عمر application باقی خواهد ماند، در نتیجه GC (مخفف Garbage Collector)، اون لیست رو Dispose نمیکنه
حالا اگر در طول برنامه اشیایی رو درون اون لیست Add کنیم عملا چون رفرنس اون اشیا داخل لیست باقی میمونن، اون اشیا هم تا پایان عمر برنامه Dispose نمیشن (حتی اگه دیگه با اون اشیا کاری نداشته باشیم) و همین عامل هست که باعث Memory Leak میشه
حالا مشابه همین اتفاق میتونه برای event ها و delegate ها هم بیافته
در واقع وقتی متدی از یک شی رو به یک event یا delegate (مانند Action و Func) توسط = یا =+ نسبت میدین، رفرنس اون شی هم Capture میشه، در نتیجه تا پایان عمر اون event یا delegate مربوطه، اون اشیاء هم باقی میمونن و Dispose نمیشن
🔹برای رفع این مشکل راه حل های مختلفی هست
1️⃣ استفاده از -= برای حذف کردن رفرنس (unsubscribe کردن) اون متد از event یا delegate مربوطه
2️⃣ استفاده از الگوی Weak Reference Pattern که توسط کلاس WeakEventHandler دات نت پیاده سازی میشه
3️⃣ استفاده از الگوی Event Aggregator Pattern که اون هم به نوعی از Weak Reference استفاده میکنه و داخل کتابخونه Prism زیاد ازش استفاده شده
و روش های دیگه که خارج از توضیح این پست هست
🔰جهت اطلاعات بیشتر و روش های جلوگیری از نشتی حافظه پیشنهاد میکنم مقالات زیر رو مطالعه کنین
✔️5 Techniques to avoid Memory Leaks by Events in C# .NET you should know
✔️Understanding and Avoiding Memory Leaks with Event Handlers and Event Aggregators
✔️Memory Leak in C#
✔️Are you afraid of event handlers because of C# memory leak?
✔️Events: Demystifying Common Memory Leaks
✔️Weak Event Patterns
_________________
@DotNetZoom
Michael's Coding Spot
5 Techniques to avoid Memory Leaks by Events in C# .NET you should know
Event registrations in C# (and .NET in general) are the most common cause of memory leaks. At least from my experience. In fact, I saw so much memory leaks from events that seeing += in code immediately makes me suspicious.
Forwarded from DotNetZoom (محمد جواد ابراهیمی)
✅ رایگان کردن مقالات سایت Medium با افزونه Medium Unlimited
مقالات خوبی تو سایت مدیوم وجود داره ولی بعضا این رایگان نبودن و قفل شدن مقالاتش رو مخه
هرچند که میشه با یه پنجره Incognito تو کروم (یا InPrivate تو مرورگر Edge) اون رو باز کرد و به رایگان استفاده کرد ولی بازم رو مخه
خلاصه اینکه اگه این قضیه رو مخ شما هم هست، راه حلش خیلی سادس؛ استفاده از فزونه Medium Unlimited
این افزونه به مدت نامحدود، مقالات سایت مدیوم رو واستون رایگان میکنه.
🔹برای مروگر FireFox میتونین توسط این لینک نصبش کنین
🔸ولی برای مروگر های Chrome و Edge جدید (که بر پایه موتور کروم هست) از طریق Web Store کروم قابل نصب نیست و باید دستی نصبش کنین.
برای این کار ابتدا:
1-فایل افزونه رو از مخزن گیتهاب پروژه دانلود کنید و فایل zip اش رو تو یه مسیری extract کنین
2- از قسمت منو گزینه Extensions رو انتخاب کنین و سپس توی صفحه ای که میاد، تیک گزینه Developer Mode رو فعال کنین
3- روی دکمه Load Unpacked کلیک کنین و مسیر پوشه افزونه که قبلا extract کردین رو بهش بدین
4- تمام، لذتشو ببرین
🔰ریپازیتوری پروژه:
https://github.com/manojVivek/medium-unlimited
____________________
@DotNetZoom
مقالات خوبی تو سایت مدیوم وجود داره ولی بعضا این رایگان نبودن و قفل شدن مقالاتش رو مخه
هرچند که میشه با یه پنجره Incognito تو کروم (یا InPrivate تو مرورگر Edge) اون رو باز کرد و به رایگان استفاده کرد ولی بازم رو مخه
خلاصه اینکه اگه این قضیه رو مخ شما هم هست، راه حلش خیلی سادس؛ استفاده از فزونه Medium Unlimited
این افزونه به مدت نامحدود، مقالات سایت مدیوم رو واستون رایگان میکنه.
🔹برای مروگر FireFox میتونین توسط این لینک نصبش کنین
🔸ولی برای مروگر های Chrome و Edge جدید (که بر پایه موتور کروم هست) از طریق Web Store کروم قابل نصب نیست و باید دستی نصبش کنین.
برای این کار ابتدا:
1-فایل افزونه رو از مخزن گیتهاب پروژه دانلود کنید و فایل zip اش رو تو یه مسیری extract کنین
2- از قسمت منو گزینه Extensions رو انتخاب کنین و سپس توی صفحه ای که میاد، تیک گزینه Developer Mode رو فعال کنین
3- روی دکمه Load Unpacked کلیک کنین و مسیر پوشه افزونه که قبلا extract کردین رو بهش بدین
4- تمام، لذتشو ببرین
🔰ریپازیتوری پروژه:
https://github.com/manojVivek/medium-unlimited
____________________
@DotNetZoom
addons.mozilla.org
Medium Unlimited: Read for free – Get this Extension for 🦊 Firefox (en-US)
Download Medium Unlimited: Read for free for Firefox. Unlocks medium.com for unlimited reads, no membership required
Forwarded from DotNetZoom (محمد جواد ابراهیمی)
✅ مفهوم Expression Tree در دات نت
میشه گفت یکی از advanced ترین قسمت های دات نت، مفهوم Expression Tree و کلاس Expression هست که یه جورایی قلب IQueryable رو هم تشکیل میده
شاید نهایت استفاده افراد، کار با <<Expression<Func برای شرط های predicate بر روی متد Where و یا selector برای متد Select باشه
ولی Expression خیلی بزرگتر از اینهاست
🔸درواقع مفهوم Expression Tree به مجموعه از از node ها در قالب یک ساختار درختی گفته میشه که هر node اون، خود یک Expression هست. اما خود Expression چیه؟
درواقع هر Expression یک operation (عملیات) برنامه نویسی رو بیان میکنه. توسط کلاس Expression در دات نت میتوان برای هر عملیات برنامه نویسی یک expression ساخت.
🔹به عنوان مثال:
- تعریف یک variable (متغیر)، constant یا parameter (پارامتر ورودی متد)
- انتصاب یک مقدار به یک variable یا parameter
- جمع، تفریق، ضرب، تقسیم و... کردن دو مقدار
- تعریف یک شرط (if/else) یا سویچ (switch) منطقی
- تعریف یک حلقه (for یا while)
- بازگرداندن (return کردن) خروجی متد
- فراخوانی یک متد، پاس دادن پارامتر های ورودی و گرفتن مقدار خروجی
- و... اکثر کار هایی که شما توسط کد نویسی میتونین انجام بدین
🔸فرق expression با کد نویسی معمولی برای operation های برنامه نویسی اینه که توسط Expression میتوان یک ساختار (data structure) قابل توصیف برای کد ها ایجاد کرد.
در نتیجه میتوان از روی این ساختار قابل توصیف، کار های متفاوت و خلاقانه ای انجام داد. مثلا میشه از روی ساختار کد هامون Transpilation انجام بدیم و کوئری (مثلا SQL) معادل اون رو تولید کرد.
🔹در واقع هنگامی که شما یک عبارت lambda رو به یکی از متد های linq که ورودی <Expression<Func داره پاس میدین، پشت صحنه به هنگام Compile یک LambdaExpression از روی عبارت lambda شما ساخته میشه و اون هست که به متد شما پاس داده میشه.
چرا؟ چون که ساختار کد شما رو لازم داره تا بتونه از روی اون Transpilation انجام بده و کوئری (مثلا SQL) معادل اون رو تولید کنه. (این مثال رو ببینید)
🔸یا حتی میتوان به کمک Transpilation، از روی یک expression یک عبارت readable (خوانا) جهت توصیف کاری که قراره انجام بده تولید کرد. همانند کاری که کتابخانه ReadableExpressions کرده و توسط افزونه ویژوال استادیو ReadableExpressions.Visualizers این امکان رو میده که به هنگام دیباگ بتونین یک readable view از روی expression هاتون ببینید
🔹کار دیگه ای که توسط Expression میشه انجام داد. تولید کد IL (مخفف Intermediate Language) از روی اون هست. مثلا شما نمیتونین توسط Reflection حتی، یک متد جدید (شامل مجمومه ای از operation ها) ایجاد کنین ولی توسط Expression میتونین به جای اینکه کد شما به هنگام compile تبدیل به IL بشه، اون رو به هنگام run-time (در زمان اجرای برنامه) از روی همون expression (که یک ساختار قابل توصیف از یک تیکه کد هست) به کد IL تبدیل کنین یا اصطلاحات Emit کنین (بیرون بدین)
در نتیجه میتونین به هنگام run-time کد جدید تولید کنین و این همون تکنیکی هست که کتابخانه های Object Mapper از جمله AutoMapper و Mapster و... از اون استفاده میکنن
🔸گفتم Emit، جا داره از Reflection.Emiit هم یادی بکنیم که پایه ای ترین روش برای تولید کد IL در زمان run-time هست و میشه Expression رو به عنوان یک wrapper روی Reflection.Emit محسوب کرد که کار با اون رو ساده تر میکنه. هرچند کار هایی میشه با Reflection.Emit انجام داد که توسط Expression Tree نمیشه انجام داد (و بلعکس) پس اینجا به هیچ عنوان جایگزین هم نیستند بلکه فقط توی تولید کد IL وجه مشترک دارند.
🔰 جمع بندی
قابلیت Expression Tree یک قابلیت پیشرفته هست و نیاز اکثر افراد نمیشه ولی مزایای غیر قابل چشم پوشی ایی رو به ما میده که حرفه ای ها میتونین کار جالبی باهاش بکنن. توسط این قابلیت که یکی از جذاب ترین امکانات دات نت هست میتونین کار های جالبی انجام بدین از جمله:
1️⃣ گردش روی node ها و فهمیدن ساختار کد (MetaProgramming)
2️⃣ ترجمه کد ها به یک زبان دیگر (Transpilation)
3️⃣ تولید کد IL از روی اون (Code Generation)
💎در آخر یکی از بهترین مقالاتی که این مفهوم رو به خوبی به همراه مثال توضیح داده مقاله زیر هست که پیشنهاد میکنم حتما بخونین
https://tyrrrz.me/blog/expression-trees
____________________
@DotNetZoom
میشه گفت یکی از advanced ترین قسمت های دات نت، مفهوم Expression Tree و کلاس Expression هست که یه جورایی قلب IQueryable رو هم تشکیل میده
شاید نهایت استفاده افراد، کار با <<Expression<Func برای شرط های predicate بر روی متد Where و یا selector برای متد Select باشه
ولی Expression خیلی بزرگتر از اینهاست
🔸درواقع مفهوم Expression Tree به مجموعه از از node ها در قالب یک ساختار درختی گفته میشه که هر node اون، خود یک Expression هست. اما خود Expression چیه؟
درواقع هر Expression یک operation (عملیات) برنامه نویسی رو بیان میکنه. توسط کلاس Expression در دات نت میتوان برای هر عملیات برنامه نویسی یک expression ساخت.
🔹به عنوان مثال:
- تعریف یک variable (متغیر)، constant یا parameter (پارامتر ورودی متد)
- انتصاب یک مقدار به یک variable یا parameter
- جمع، تفریق، ضرب، تقسیم و... کردن دو مقدار
- تعریف یک شرط (if/else) یا سویچ (switch) منطقی
- تعریف یک حلقه (for یا while)
- بازگرداندن (return کردن) خروجی متد
- فراخوانی یک متد، پاس دادن پارامتر های ورودی و گرفتن مقدار خروجی
- و... اکثر کار هایی که شما توسط کد نویسی میتونین انجام بدین
🔸فرق expression با کد نویسی معمولی برای operation های برنامه نویسی اینه که توسط Expression میتوان یک ساختار (data structure) قابل توصیف برای کد ها ایجاد کرد.
در نتیجه میتوان از روی این ساختار قابل توصیف، کار های متفاوت و خلاقانه ای انجام داد. مثلا میشه از روی ساختار کد هامون Transpilation انجام بدیم و کوئری (مثلا SQL) معادل اون رو تولید کرد.
🔹در واقع هنگامی که شما یک عبارت lambda رو به یکی از متد های linq که ورودی <Expression<Func داره پاس میدین، پشت صحنه به هنگام Compile یک LambdaExpression از روی عبارت lambda شما ساخته میشه و اون هست که به متد شما پاس داده میشه.
چرا؟ چون که ساختار کد شما رو لازم داره تا بتونه از روی اون Transpilation انجام بده و کوئری (مثلا SQL) معادل اون رو تولید کنه. (این مثال رو ببینید)
🔸یا حتی میتوان به کمک Transpilation، از روی یک expression یک عبارت readable (خوانا) جهت توصیف کاری که قراره انجام بده تولید کرد. همانند کاری که کتابخانه ReadableExpressions کرده و توسط افزونه ویژوال استادیو ReadableExpressions.Visualizers این امکان رو میده که به هنگام دیباگ بتونین یک readable view از روی expression هاتون ببینید
🔹کار دیگه ای که توسط Expression میشه انجام داد. تولید کد IL (مخفف Intermediate Language) از روی اون هست. مثلا شما نمیتونین توسط Reflection حتی، یک متد جدید (شامل مجمومه ای از operation ها) ایجاد کنین ولی توسط Expression میتونین به جای اینکه کد شما به هنگام compile تبدیل به IL بشه، اون رو به هنگام run-time (در زمان اجرای برنامه) از روی همون expression (که یک ساختار قابل توصیف از یک تیکه کد هست) به کد IL تبدیل کنین یا اصطلاحات Emit کنین (بیرون بدین)
در نتیجه میتونین به هنگام run-time کد جدید تولید کنین و این همون تکنیکی هست که کتابخانه های Object Mapper از جمله AutoMapper و Mapster و... از اون استفاده میکنن
🔸گفتم Emit، جا داره از Reflection.Emiit هم یادی بکنیم که پایه ای ترین روش برای تولید کد IL در زمان run-time هست و میشه Expression رو به عنوان یک wrapper روی Reflection.Emit محسوب کرد که کار با اون رو ساده تر میکنه. هرچند کار هایی میشه با Reflection.Emit انجام داد که توسط Expression Tree نمیشه انجام داد (و بلعکس) پس اینجا به هیچ عنوان جایگزین هم نیستند بلکه فقط توی تولید کد IL وجه مشترک دارند.
🔰 جمع بندی
قابلیت Expression Tree یک قابلیت پیشرفته هست و نیاز اکثر افراد نمیشه ولی مزایای غیر قابل چشم پوشی ایی رو به ما میده که حرفه ای ها میتونین کار جالبی باهاش بکنن. توسط این قابلیت که یکی از جذاب ترین امکانات دات نت هست میتونین کار های جالبی انجام بدین از جمله:
1️⃣ گردش روی node ها و فهمیدن ساختار کد (MetaProgramming)
2️⃣ ترجمه کد ها به یک زبان دیگر (Transpilation)
3️⃣ تولید کد IL از روی اون (Code Generation)
💎در آخر یکی از بهترین مقالاتی که این مفهوم رو به خوبی به همراه مثال توضیح داده مقاله زیر هست که پیشنهاد میکنم حتما بخونین
https://tyrrrz.me/blog/expression-trees
____________________
@DotNetZoom
Oleksii Holub
Working with Expression Trees in C# • Oleksii Holub
Expression trees is an obscure, although very interesting feature in .NET. Most people probably think of it as something synonymous with object-relational mapping frameworks, but despite being its most common use case, it's not the only one. There are a…