مطالب
آموزش فایرباگ - #1
فایرباگ نام ابزاری است که همه ما نام آن را شنیده ایم یا با آن کار کرده ایم .
این ابزار امکانات و قابلیت‌های فراوانی دارد که فراگیری آنها برای یک توسعه گر یا طراح وب سایت ضروری به نظر می‌رسد .
در سری مقالات آموزش فایرباگ ، با این ابزار محبوب و پرکاربرد بیشتر آشنا می‌شویم .


نصب و اجرای فایرباگ :
ابتدا وارد این صفحه شوید و ورژن مناسب مرورگرتان را نصب نمایید .
پس از نصب و دوباره باز کردن مرورگر ، میتوانید با کلیک کردن بروی آیکون فایرباگ یا فشردن کلید F12 ، فایرباگ را اجرا کنید .


تب‌ها :
فایرباگ در حالت پیشفرض دارای 6 تب می‌باشد .
  • Console : در این تب دو بخش وجود دارد :
    در بخش Log هشدار‌ها ، پیغام‌ها ، درخواست‌های XHR و ... نمایش داده می‌شوند .
    بخش دیگر هم که در سمت راست قرار دارد ، مخصوص اجرای کدهای جاوا اسکریپت می‌باشد .



  • HTML : در این تب HTML صفحه را بصورت درختی و بصورت Live مشاهده می‌کنید .
    Live بودن به این معنی است دقیقا چیزی را مشاهده می‌کنید که مرورگر در حال تفسیر هست و نه چیزی که به مرورگر ارسال شده .
    همچنین در این تب می‌توانید محتوای HTML قسمت Body صفحه را ویرایش کنید .


  • CSS : در این تب می‌توانید تعاریف CSS موجود در صفحه را مشاهده/ویرایش/حذف/فعال-غیرفعال نمایید .
    همچنین می‌توانید تمام فایل‌های استایلی که به صفحه اضافه شده اند را مشاهده و تعیین کنید که تعاریف موجود در کدام فایل‌ها در این محیط نمایش داده بشوند .




  • Script : در این تب می‌توانید به خطایابی کدهای جاوا اسکریپت بپردازید . همچنین مانند تب CSS می‌توانید یکی از فایل‌های اضافه شده به صفحه برای نمایش در این بخش ، چند مورد را انتخاب کنید .



  • DOM : در این تب می‌توانید ساختار DOM صفحه جاری را مشاهده نمایید .


  • Net : در این تب می‌توانید درخواست هایی که از صفحه ارسال می‌شوند را زیر نظر بگیرید .
    این تب اطلاعات کاملی درباره‌ی هر درخواست ارائه می‌کند .
    از جمله : نوع درخواست ( Post/Get ) ، حجم درخواست و پاسخ ، مدت زمان درخواست ، تعداد درخواست‌های ارسال شده ، وضعیت درخواست‌ها و ...



در قسمت‌های بعدی هر تب را به صورت جداگانه بررسی می‌کنیم .
مطالب
بررسی اجمالی Redis
نام Redis از Remote Dictionary server گرفته شده‌است. Redis یکی از محبوب‌ترین key-value store‌ها می‌باشد و هم چنین توسط برند‌های بزرگ IT جهان استفاده می‌شود. لازم به ذکر است  Amazon Elastic Cache از Redis پشتیبانی می‌کند. Redis یک دیتابیس No SQL است و بر روی مفهوم زوج  کلید-مقدار (key-value ) کار می‌کند. key-value store امکانی را برای ذخیره داده‌ها که Value  نامیده میشود، در یک Key فراهم می‌کند. شما می‌توانید بعدا این داد‌ه‌ها را دریافت کنید، تنها اگر نام دقیق کلیدی را که برای ذخیره داده استفاده کرده‌اید، بدانید.

What Is In-Memory, Key-Value Store  

Key-Value store یک سیستم ذخیره سازی است؛ جایی که داده‌ها به صورت زوج کلید-مقدار ذخیره می‌شوند. وقتی که میگوییم in-memory key-value store (زوج کلید-مقدار مقیم در حافظه)، منظور این است که زوج کلید-مقدار در حافظه اصلی RAM ذخیره می‌شوند. بنابراین می‌توانیم بگوییم Redis داده‌ها را در حافظه به شکل زوج کلید-مقدار ذخیره کرده است. 
در Redis کلید‌ها باید string باشند؛ ولی value ‌ها می‌توانند یک string ، list ، set ، sorted set یا hash باشند. 
 
Advantage And Disadvantage of Redis over DBMS  

Database Management systems همه چیز را در حافظه ثانویه ذخیره می‌کند که باعث می‌شود خواندن و نوشتن عملیات، تا اندازه‌ای کند باشد. این در حالی است که Redis  همه چیز را در حافظه اصلی ذخیره می‌کند و همین موضوع باعث می‌شود که خواندن و نوشتن داده‌ها توسط آن خیلی سریع باشند. 
حافظه اصلی محدود است. بنابراین Redis نمی‌تواند فایل‌های بزرگ یا binary data را ذخیره کند و تنها اطلاعات متنی کوچک را ذخیره می‌کند که نیاز است قابل دسترسی و اصلاح باشند و با نرخ خیلی سریعی قابل درج باشند. اگر تلاش کنیم که داده‌های بیشتری را نسبت به حافظه موجود بنویسیم، در این حالت خطا دریافت خواهیم کرد.

 Redis  RDBMS
Redis  همه چیز را در حافظه اصلی ذخیره می‌کند. RDBMS همه چیز را در حافظه ثانویه ذخیره می‌کند.
در Redis بخاطر ذخیره سازی داده‌ها در حافظه اصلی، خواندن و نوشتن عملیات به شدت سریع می‌باشد. در RDBMS بخاطر ذخیره سازی داده‌ها در حافظه ثانویه، خواندن و نوشتن
عملیات کند است.
حافظه اصلی از نظر size کوچکتر و از لحاظ قیمت نسبت به حافظه ثانویه گرانتر می‌باشد. Redis نمی‌تواند داده‌های بزرگ یا binary data را ذخیره کند.    حافظه ثانویه از نظر size  بزرگتر و از لحاظ قیمت نسبت به حافظه اصلی ارزان‌تر می‌باشد. RDBMS به آسانی می‌تواند با انواع فایل‌ها کار کند.   


Redis Advantages

  • Redis  : Exceptionally fast خیلی سریع است و می‌تواند حدود 110000  ، SET   و 81000 ،  GET را به ازای هر ثانیه انجام دهد.
  • Redis : Supports rich data type بیشتر دیتا تایپ‌ها را  که توسعه دهندگان قبلا آن‌ها را شناخته‌اند، پشتیبانی می‌کند؛ از قبیل string ، list ، set ، sorted set یا hash .
  •  Operations are atomic  : تمام عملیات Redis اتمیک می‌باشند که این اطمینان خاطر را میدهد اگر دو کلاینت به صورت همزمان به آن دسترسی داشته باشند، Redis server مقدار update شده را دریافت خواهد کرد. 
  • Redis : Multi-utility tool یک ابزار چند منظوره است که می‌تواند در برخی از سناریو‌ها استفاده شود از قبیل:  Redis ) messaging-queues , caching   به صورت بومی از Publish/Subscribe پشتیبانی می‌کند ) , هر داده ای با طول عمر کوتاه در Application مانند web application sessions , ... .
 

Redis Single Instance Architecture 

معماری Redis شامل دو پروسه اصلی است: 
1- Redis client
2- Redis Server


Redis client و Redis Server هر دو می‌توانند در یک کامپیوتر یا کامپیوتر‌های متفاوت باشند. Redis server مسئول ذخیره سازی داده‌ها در حافظه می‌باشد. همانطور که متوجه هستیم، Redis همه چیز را در حافظه اصلی ذخیره می‌کند و حافظه اصلی فرار است؛ از این رو زمانیکه Redis server یا کامپیوتر را راه اندازی مجدد (restart) می‌کنیم، همه داده‌های ذخیره شده را از دست خواهیم داد. بنابراین نیازمند یک راه‌حل، جهت ماندگاری datastore می‌باشیم. 


Redis Persistance 
 
سه راه متفاوت وجود دارد که Redis را پایدار می‌کند : RDB ، AOF و دستور SAVE

1-  RDB : RDB Mechanism یک نمونه از تمام داده‌های در حافظه را تهیه و آن‌ها را در حافظه ثانویه ذخیره می‌کند (ذخیره سازی ماندگار) که در یک وقفه مشخص اتفاق می‌افتد. بنابراین این شانس وجود دارد که شما داده‌هایی را از دست بدهید که بعد از آخرین Set , RDB’s snapshot  شده‌اند . 

2-AOF : AOF همه عملیات نوشتن دریافت شده توسط سرور را ثبت می‌کند. بنابراین همه چیز پایدار است. مشکل استفاده از AOF  این است که برای هر عملیات، شروع به نوشتن در دیسک می‌کند و این یک کار هزینه‌بر است و هم چنین اندازه فایل AOF بزرگتر از RDB می‌باشد. 

3-SAVE Command : شما می‌توانید Redis server را مجبور کنید که یک RDB snapshot را ایجاد کند؛ هر زمانکه Redis console client از دستور SAVE استفاده می‌کند.

در ضمن می‌توانید از AOF  و RDB با هم استفاده کنید تا بهترین نتیجه ماندگاری را داشته باشید. 
 
Redis Replication 

Replication یک تکنیک است که کامپیوتر‌ها را درگیر می‌کند تا دسترسی پذیری داده‌ها و تحمل خطا را با ضریب بیشتری امکان پذیر کنند. در یک محیط Replication، کامپیوتر‌ها، داده‌های یکسانی را با یکدیگر به اشتراک می‌گذارند؛ حتی اگر چندین کامپیوتر دچار مشکل شوند، باز هم، همه داده‌ها در دسترس خواهند بود که به صورت Master/Slaves  می‌باشند.


تمام slave‌ها شامل داده‌های یکسانی همانند master می‌باشند. وقتی‌که یک slave جدید در محیط Replication ایجاد می‌شود، master به صورت خودکار همه داده‌ها را با sync ، slave می‌کند.
تمام Query ‌ها به سرور master هدایت می‌شوند و سپس سرور master عملیات را اجرا می‌کند. وقتی‌که یک عملیات نوشتن اتفاق می‌افتد، سرور master داده‌هایی را که به‌تازگی نوشته شده‌اند، در تمام slave‌ها تکثیر می‌کند. 
 اگر اتفاقی در سرور master رخ دهد، تمام داده‌ها از بین می‌روند؛ در این حالت باید یک slave را به master تبدیل کنیم. 

Clustering In Redis 

Clustering یک تکنیک می‌باشد که توسط آن می‌توان داده‌ها را در چندین کامپیوتر تقسیم بندی کرد. فرض کنید که یک سرور Redis را با 64GB حافظه در اختیار داریم. در این حالت می‌توانیم 64GB داده داشته باشیم. اگر  10 تا clustered computer را که هر کدام 64GB حافظه اصلی دارند، داشته باشیم، در این حالت می‌توان 640GB  داده را ذخیره کرد. 
 

در تصویر بالا می‌توانیم ببینیم که داده‌ها در چهار node، ذخیره شده‌اند. هر node یک Redis Server پیکربندی شده می‌باشد؛ به عنوان یک cluster node. اگر یکی از node ‌ها دچار مشکل شوند، سپس کل cluster متوقف می‌شود. 

Redis Client 

وب سایت Try Redis ، یک Redis console client  آنلاین است و به شما کمک می‌کند تا یاد بگیرید چگونه از Redis console client  استفاده کنید.


در قسمت بعد در رابطه با نصب Redis  بر روی سیستم عامل ویندوز و دیتا تایپ‌ها در Redis صحبت خواهیم کرد.
نظرات مطالب
مروری بر قابلیت جدید ASP.NET FriendlyUrls
خیلی لطف کردین فقط یه سوال دیگه
فایل‌های js اضافه کردم به اسکریپت منیجر درست شد
اما فایل css  را چی کار کنم
مطالب
معرفی Selector های CSS - قسمت 5
41- :checked
برای تگ‌های radio و checkbox استفاده می‌شود و آنهایی را انتخاب می‌کند که گزینه‌ی آن‌ها انتخاب شده است یا شامل ویژگی checked می‌باشند.
<style>
    :checked {
        width: 50px;
        height: 50px;
    }
</style>
<input type="checkbox" checked="checked"/>
<input type="checkbox"/>
<input type="radio" name="test"/>
<input type="radio" name="test" checked="checked"/>
<input type="radio" name="test"/>
در مثال فوق تمامی checkbox هایی که گزینه‌ی آن‌ها انتخاب شده‌اند با ابعاد 50 در 50 نمایش می‌یابند.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :checked  3

42- :indeterminate
در HTML نمی‌توان وضعیت indeterminate را برای checkbox ایجاد نمود. اما با جاوا اسکریپت می‌توان این وضعیت را ایجاد کرد. هر checkbox می‌تواند دارای سه وضعیت انتخاب شده، انتخاب نشده و نامعلوم (indeterminate) باشد. این Selector تگهای checkbox ی را انتخاب می‌نماید که وضعیت نامعلوم دارند.
<style>
    :indeterminate {
        width: 50px;
        height: 50px;
    }
</style>
<input type="checkbox" id="chk1"/>
<input type="checkbox" id="chk2" checked="checked"/>
<input type="checkbox" id="chk3"/>
<script>
    document.getElementById("chk1").indeterminate=true;
</script>
در مثال فوق chk1 به صورت indeterminate انتخاب شده است که با ابعاد 50 در 50 نمایش می‌یابد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 No   No   No  No 
 No :indeterminate  4

43- :default
برای تگ‌های radio و checkbox، آنهایی را انتخاب می‌کند که در زمان بارگزاری فرم و بصورت پیش فرض انتخاب شده‌اند. برای دکمه‌ی submit ایی نیز استفاده می‌شود که در حال حاضر در فرم فعال می‌باشد. پشتیبانی از این Selector در مرورگرها متفاوت می‌باشد؛ بنابراین در چند مرورگر کارآیی آن را بررسی کنید.
<style>
    :default {
        width: 50px;
        height: 50px;
        background: lime;
    }
</style>
<form>
    <input type="checkbox" checked="checked" />
    <input type="checkbox" />
    <input type="radio" name="radio1" />
    <input type="radio" name="radio1" checked="checked" />
    <input type="radio" name="radio1" />
    <input type="submit" value="Default" />
    <input type="submit" value="Submit 2" />
</form>
در مثال فوق checkbox و radio هایی که در لود اولیه فرم دارای ویژگی checked می‌باشند به همراه دکمه‌ی submit با عنوان Default با ابعاد 50 در 50 و رنگ پس زمینه‌ی لیمویی نمایش می‌یابند.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 No   No   No  No 
 No :default  4

44- :root
المنت ریشه‌ی یک صفحه را انتخاب می‌نماید. معمولا تگ html به عنوان المنت ریشه انتخاب می‌شود.
<style>
    :root {
        background: khaki;
    }
</style>
در مثال فوق رنگ پس زمینه به رنگ خاکی نمایش می‌یابد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :root  3

45- :after
جهت درج محتوا بعد از تگ استفاده می‌شود.
<style>
    form:after {
        content: "[ * : Required]";
        color: red;            
    }
        input+span:after {
            content: ' * ';
            color: red;
        }
</style>
<form>
    <div><input type="text" /><span></span></div>
    <div><input type="password" /><span></span></div>
    <div><input type="email" /><span></span></div>
</form>
در مثال فوق بعد از تمامی span‌های قرار گرفته در کنار تگ‌های input، یک کاراکتر * را به رنگ قرمز نمایش میدهد. بعد از فرم نیز رشته‌ی [ * : Required] را به رنگ قرمز نمایش می‌دهد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.1 7.0  9.0 3.5  4.0 :after 2

46- :before
جهت درج محتوا قبل از تگ استفاده می‌شود.
<style>
    form:before {
        content: "[ * : Required]";
        color: red;
    }

    input + span:before {
        content: ' * ';
        color: red;
    }
</style>
<form>
    <div><input type="text" /><span></span></div>
    <div><input type="password" /><span></span></div>
    <div><input type="email" /><span></span></div>
</form>
در مثال فوق قبل از تمامی span‌های قرار گرفته در کنار تگ‌های input، یک کاراکتر * را به رنگ قرمز نمایش می‌دهد. قبل از فرم نیز رشته‌ی [ * : Required] را به رنگ قرمز نمایش می‌دهد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.1 7.0  9.0 3.5  4.0 :before 2

47- ::selection
محتوایی را انتخاب می‌کند که در حال حاضر در صفحه انتخاب یا Select شده‌است.
<style>
    ::selection {
        background: navy;
        color: orange;
    }
</style>
<p>
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. 
    Maecenas porttitor congue massa. Fusce posuere, 
    magna sed pulvinar ultricies, purus lectus malesuada libero, 
    sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. Fusce est.
</p>
در مثال فوق با انتخاب متن توسط ماوس، رنگ زمینه‌ی متن انتخاب شده به صورت سرمه ای و رنگ متن آن نارنجی نمایش می‌یابد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.1  9.6  9.0 2.0
-moz-
 4.0 ::selection  در CSS 3 معرفی و سپس حذف شد ولی امکان بازگشت مجدد وجود دارد

48- :not(S1,S2)
تگ هایی را انتخاب می‌کند که شامل Selector‌های S1 یا S2 یا ... یا Sn نباشند.
<style>
    :not([readonly]) {
        background: yellow;
    }
</style>
<input type="text"/>
<input type="text" readonly="readonly"/>
<input type="text"/>
<input type="text" readonly="readonly" />
در مثال فوق پس زمینه‌ی تگهای input که ویژگی readonly ندارند به رنگ زرد نمایش می‌یابند.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :not(S1,S2)  3

49- :matches(S1,S2)
تگ هایی را انتخاب می‌کند که شامل Selector‌های S1 و/یا S2 و/یا ... و/یا Sn باشند. 
<style>
    :matches([readonly]) {
        background: yellow;
    }
</style>
<input type="text" />
<input type="text" readonly="readonly" />
<input type="text" />
<input type="text" readonly="readonly" />
در مثال فوق پس زمینه‌ی تگهای input که ویژگی readonly دارند به رنگ زرد نمایش می‌یابند. 
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 No   No   No  No 
 No :matches(S1,S2)  4

50- :has(S1,S2)
تگ هایی را انتخاب می‌کند که در ارتباط خاصی با Selector های S1 و/یا S2 و/یا ... و/یا Sn می‌باشند. 
<style>
    :has(>span) {
        color: red;
    }
    :has(+div) {
        color: blue;
    }
</style>
<div>
    <p>
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Maecenas <span>porttitor</span> congue massa. Fusce posuere,
        magna sed pulvinar ultricies, purus lectus malesuada libero,
        sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. Fusce est.
    </p>
    <h1>Header 1</h1>
    <div>
            
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
        Maecenas porttitor congue massa. Fusce posuere,
        magna sed pulvinar ultricies, purus lectus malesuada libero,
        sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. Fusce est.            
    </div>
در مثال فوق متن موجود در تگ p که دارای فرزند مستقیم span می‌باشد، با توجه به Selector ی که بصورت :has(>span) تعریف شده است، به رنگ قرمز نمایش می‌یابد. همچنین Header 1 که دارای تگ div هم تراز و دقیقا بعد از h1 است، با توجه به Selector ی که بصورت  :has(+div) تعریف شده است، به رنگ آبی نمایش می‌یابد.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 No   No   No  No 
 No :has(S1,S2)  4 
مطالب
C# 12.0 - Interceptors
به C# 12 و دات‌نت 8، ویژگی «آزمایشی» جدیدی به نام Interceptors اضافه شده‌است که به آن «monkey patching» هم می‌گویند. هدف از آن، جایگزین کردن یک پیاده سازی، با پیاده سازی دیگری است. به این ترتیب توسعه دهندگان دات‌نتی می‌توانند فراخوانی متدهایی خاص را ره‌گیری کرده (interception) و سپس آن‌را به فراخوانی یک پیاده سازی جدید، هدایت کنند.


Interceptor چیست؟

از زمان ارائه‌ی NET 8 preview 6 SDK. به بعد، امکان ره‌گیری هر متدی از کدهای برنامه، به دات‌نت اضافه شده‌است؛ به همین جهت از واژه‌ی Interceptor/ره‌گیر در اینجا استفاده می‌شود. خود تیم دات‌نت از این قابلیت در جهت بازنویسی پویای قسمت‌هایی از کدهای زیرساخت دات‌نت که از Reflection استفاده می‌کنند، با نگارش‌های کامپایل شده‌ی مختص به برنامه‌ی شما، کمک می‌گیرند. به این ترتیب سرعت و کارآیی برنامه‌های دات‌نت 8، بهبود قابل ملاحظه‌ای را پیدا کرده‌اند. برای مثال ahead-of-time compilation (AOT) در دات‌نت 8 و ASP.NET Core 8x بر اساس این ویژگی پیاده سازی شده‌است. این ویژگی جدید، مکمل source generators است که در نگارش‌های پیشین دات‌نت ارائه شده بود.


بررسی  Interceptors با تهیه‌ی یک مثال ساده

فرض کنید می‌خواهیم فراخوانی متد GetText زیر را ره‌گیری کرده و سپس آن‌را با نمونه‌ی دیگری جایگزین کنیم:
namespace CS8Tests;

public class InterceptorsSample
{
    public string GetText(string text)
    {
        return $"{text}, World!";
    }
}
برای اینکار ابتدا نیاز است یک فایل جدید را به نام InterceptsLocationAttribute.cs با محتوای زیر به پروژه اضافه کرد:
namespace System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
public sealed class InterceptsLocationAttribute : Attribute
{
    public InterceptsLocationAttribute(string filePath, int line, int character)
    {
    }
}
همانطور که در مقدمه‌ی بحث هم عنوان شد، این ویژگی هنوز آزمایشی است و نهایی نشده و ویژگی فوق نیز هنوز به دات‌نت اضافه نشده‌است. به همین جهت فعلا باید آن‌را به صورت دستی به پروژه اضافه کرد و احتمالا در نگارش‌های بعدی دات‌نت، امضای آن تغییر خواهد کرد ... یا حتی ممکن است بطور کامل حذف شود!

سپس فرض کنید فراخوانی متد GetText در فایل Program.cs برنامه به صورت زیر انجام شده‌است:
using CS8Tests;

var example = new InterceptorsSample();
var text = example.GetText("Hello");
Console.WriteLine(text); //Hello, World!
یعنی متد GetText، در سطر چهارم و کاراکتر 20 ام آن فراخوانی شده‌است. این اعداد مهم هستند!

در ادامه از این اطلاعات در ره‌گیر سفارشی زیر استفاده خواهیم کرد:
using System.Runtime.CompilerServices;

namespace CS8Tests;

public static class MyInterceptor
{
    [InterceptsLocation("C:\\Path\\To\\CS8Tests\\Program.cs", 4, 20)] 
    public static string InterceptorMethod(this InterceptorsSample example, string text)
    {
        return $"{text}, DNT!";
    }
}
این ره‌گیر که به صورت متدی الحاقی برای کلاس InterceptorsSample دربرگیرنده‌ی متد GetText تهیه می‌شود، کار جایگزینی فراخوانی آن‌را در سطر چهارم و کاراکتر 20 ام فایل Program.cs انجام می‌دهد. امضای پارامترهای این متد، باید با امضای پارامترهای متد ره‌گیری شده، یکی باشد.

اکنون اگر برنامه را اجرا کنیم ... با خطای زیر مواجه می‌شویم:
 error CS9137: The 'interceptors' experimental feature is not enabled in this namespace. Add
'<InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);CS8Tests</InterceptorsPreviewNamespaces>'
to your project.
عنوان می‌کند که این ویژگی آزمایشی است و باید فایل csproj. را به صورت زیر تغییر داد تا بتوان از آن استفاده نمود:
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <!--<NoWarn>Test001</NoWarn>-->
    <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);CS8Tests</InterceptorsPreviewNamespaces>
  </PropertyGroup>
</Project>
اینبار برنامه کامپایل شده و اجرا می‌شود. در این حالت خروجی جدید برنامه، خروجی تامین شده‌ی توسط ره‌گیر سفارشی ما است:
Hello, DNT!


سؤال: آیا ره‌گیری انجام شده، در زمان کامپایل انجام می‌شود یا در زمان اجرا؟

برای این مورد می‌توان به Low-Level C# code تولیدی مراجعه کرد. برای مشاهده‌ی یک چنین کدهایی می‌توانید از منوی Tools->IL Viewer برنامه‌ی Rider استفاده کرده و در برگه‌ی ظاهر شده، گزینه‌ی Low-Level C# آن‌را انتخاب نمائید:
using CS8Tests;
using System;
using System.Runtime.CompilerServices;

[CompilerGenerated]
internal class Program
{
  private static void <Main>$(string[] args)
  {
    Console.WriteLine(new InterceptorsSample().InterceptorMethod("Hello"));
  }

  public Program()
  {
    base..ctor();
  }
}
همانطور که مشاهده می‌کنید، این ره‌گیری و جایگزینی، در زمان کامپایل انجام شده و کامپایلر، به‌طور کامل نحوه‌ی فراخوانی متد GetText اصلی را به متد ره‌گیر ما تغییر داده و بازنویسی کرده‌است.


سؤال: آیا این قابلیت واقعا کاربردی است؟!

اکنون شاید این سؤال مطرح شود که ... واقعا چه کسی قرار است مسیر کامل یک فایل، شماره سطر و شماره ستون فراخوانی متدی را به اینگونه در اختیار سیستم ره‌گیری قرار دهد؟! آیا واقعا این قابلیت، یک قابلیت کاربردی و مناسب است؟!
اینجا است که اهمیت source generators مشخص می‌شود. توسط source generators دسترسی کاملی به syntax trees وجود دارد و همچنین یکسری اطلاعات تکمیلی مانند FilePath و سپس CSharpSyntaxNodeها که دسترسی به داده‌های متد ()GetLocation را دارند که مکان دقیق سطر و ستون‌های فراخوانی‌ها را مشخص می‌کند.


کاربردهای فعلی ره‌گیرها در دات نت 8

در دات نت 8، این موارد با استفاده از ره‌گیرها بهینه سازی شده و سرعت آن‌ها افزایش یافته‌اند:
- فراخوانی‌هایی که تمام اطلاعات آن‌ها در زمان کامپایل فراهم است، مانند Regex.IsMatch(@"a+b+") که از یک الگوی ثابت و مشخص استفاده می‌کند، ره‌گیری شده و پیاده سازی آن با کدی استاتیک، جایگزین می‌شود.
- در ASP.NET Minimal API، استفاده از lambda expressions جهت ارائه‌ی تعاریفی مانند:
app.MapGet("/products", handler: (int? page, int? pageLength, MyDb db) => { ... })
مرسوم است. این نوع فراخوانی‌ها نیز توسط ره‌گیرها برای جایگزینی handler آن‌ها با کدهای استاتیک، جهت بالابردن کارآیی و کاهش تخصیص‌های حافظه انجام می‌شود.
- بهبود کارآیی foreach loops جهت استفاده از ریاضیات برداری و SIMD در صورت امکان.
- بهبود کارآیی تزریق وابستگی‌ها، زمانیکه به تعاریف مشخصی مانند ()<provider.Register<MyService ختم می‌شود.
- بجای استفاده از expression trees در زمان اجرای برنامه، اکنون می‌توان کدهای SQL معادل را در زمان کامپایل برنامه تولید کرد.
- بهبود کارآیی Serializers، زمانیکه از یک نوع مشخص مانند ()<Serialize<MyType استفاده می‌شود و کامپایلر می‌تواند آن‌را با کدهای زمان کامپایل، جایگزین کند.


محدودیت‌های ره‌گیرها در دات‌نت 8

- ره‌گیرهای دات‌نت 8 فقط با متدها کار می‌کنند.
- مسیر ارائه شده حتما باید یک مسیر کامل و مشخص باشد. یعنی اگر این قطعه کد، به سیستم دیگری منتقل شود، کامپایل نخواهد شد و امکان ارائه‌ی مسیرهای نسبی وجود ندارد.
- امضای متدها، حتما باید یکی باشد. یعنی نمی‌توان یک ره‌گیر جنریک را تعریف کرد.
مطالب
آشنایی با CLR: قسمت هفتم
کدهای IL و تایید آن ها

ساختار استکی
IL از ساختار استک استفاده می‌کند. به این معنی که تمامی دستور العمل‌ها داخل آن push شده و نتیجه‌ی اجرای آن‌ها pop می‌شوند. از آنجا که IL به طور مستقیم ارتباطی با ثبات‌ها ندارد، ایجاد زبانهای برنامه نویسی جدید بر اساس CLR بسیار راحت‌تر هست و عمل کامپایل، تبدیل کردن به کدهای IL می‌باشد.

بدون نوع بودن(Typeless)
از دیگر مزیت‌های آن این است که کدهای IL بدون نوع هستند. به این معنی که موقع افزودن دستورالعملی به داخل استک، دو عملگر وارد می‌شوند و هیچ جداسازی در رابطه با سیستم‌های 32 یا 64 بیت صورت نمی‌گیرد و موقع اجرای برنامه است که تصمیم می‌گیرد از چه عملگرهایی باید استفاده شود.

Virtual Address Space
بزرگترین مزیت این سیستم‌ها امنیت و مقاومت آن هاست. موقعی که تبدیل کد IL به سمت کد بومی صورت می‌گیرد، CLR فرآیندی را با نام verification یا تاییدیه، اجرا می‌کند. این فرآیند تمامی کدهای IL را بررسی می‌کند تا از امنیت کدها اطمینان کسب کند. برای مثال بررسی می‌کند که هر متدی صدا زده می‌شود با تعدادی پارامترهای صحیح صدا زده شود و به هر پارامتر آن نوع صحیحش پاس شود و مقدار بازگشتی هر متد به درستی استفاده شود. متادیتا شامل اطلاعات تمامی پیاده سازی‌ها و متدها و نوع هاست که در انجام تاییدیه مورد استفاده قرار می‌گیرد.
در ویندوز هر پروسه، یک آدرس مجازی در حافظه دارد و این جدا سازی حافظه و ایجاد یک حافظه مجازی کاری لازم اجراست. شما نمی‌توانید به کد یک برنامه اعتماد داشته باشید که از حد خود تخطی نخواهد کرد و فرآیند برنامه‌ی دیگر را مختل نخواهد کرد. با خواندن و نوشتن در یک آدرس نامعتبر حافظه، ما این اطمینان را کسب می‌کنیم که هیچ گاه تخطی در حافظه صورت نمی‌گیرد.
قبلا به طور مفصل در این مورد ذخیره سازی در حافظه صحبت کرده ایم.

Hosting
از آنجا که پروسه‌های ویندوزی به مقدار زیادی از منابع سیستم عامل نیاز دارند که باعث کاهش منابع و محدودیت در آن می‌شوند و نهایت کارآیی سیستم را پایین می‌آورد، ولی با کاهش تعدادی برنامه‌های در حال اجرا به یک پروسه‌ی واحد می‌توان کارآیی سیستم را بهبود بخشید و منابع کمتری مورد استفاده قرار می‌گیرند که این یکی دیگر از مزایای کدهای managed نسبت به unmanaged است. CLR در حقیقت این قابلیت را به شما می‌دهد تا چند برنامه‌ی مدیریت شده را در قالب یک پروسه به اجرا درآورید. هر برنامه‌ی مدیریت شده به طور پیش فرض بر روی یک appDomain اجرا می‌گردد و هر فایل EXE روی حافظه‌ی مجازی مختص خودش اجرا می‌شود. هر چند پروسه‌هایی از قبیل IIS و SQL Server که پروسه‌های CLR را پشتیبانی یا هاست می‌کنند می‌توانند تصمیم بگیرند که آیا appDomain‌ها را در یک پروسه‌ی واحد اجرا کنند یا خیر که در مقاله‌های آتی آن را بررسی می‌کنیم.

کد ناامن یا غیر ایمن UnSafe Code
به طور پیش فرض سی شارپ کدهای ایمنی را تولید می‌کند، ولی این اجازه را می‌دهد که اگر برنامه نویس بخواهد  کدهای ناامن بزند، قادر به انجام آن باشد. این کدهای ناامن دسترسی مستقیم به خانه‌های حافظه و دستکاری بایت هاست. این مورد قابلیت قدرتمندی است که به توسعه دهنده اجازه می‌دهد که با کدهای مدیریت نشده ارتباط برقرار کند یا یک الگوریتم با اهمیت زمانی بالا را جهت بهبود کارآیی، اجرا کند.
 هر چند یک کد ناامن سبب ریسک بزرگی می‌شود و می‌تواند وضعیت بسیاری از ساختارهای ذخیره شده در حافظه را به هم بزند و امنیت برنامه را تا حد زیادی کاهش دهد.  به همین دلیل سی شارپ نیاز دارد تا تمامی متدهایی که شامل کد unsafe هستند را با کلمه کلیدی unsafe علامت گذاری کند. همچنین کمپایلر سی شارپ نیاز دارد تا شما این کدها را با سوئیچ unsafe/ کامپایل کنید.

موقعیکه جیت تلاش دارد تا یک کد ناامن را کامپایل کند، اسمبلی را بررسی می‌کند که آیا این متد اجازه و تاییدیه آن را دارد یا خیر. آیا  System.Security.Permissions.SecurityPermission با فلگ SkipVerification مقدار دهی شده است یا خیر. اگر پاسخ مثبت بود JIT آن‌ها را کامپایل کرده و اجازه‌ی اجرای آن‌ها را می‌دهد. CLR به این کد اعتماد می‌کند و امیدوار است که آدرس دهی مستقیم و دستکاری بایت‌های حافظه موجب آسیبی نگردد. ولی اگر پاسخ منفی بود، یک استثناء از نوع System.InvalidProgramException یا System.Security.VerificationException را ایجاد می‌کند تا از اجرای این متد جلوگیری به عمل آید. در واقع کل برنامه خاتمه میابد ولی آسیبی به حافظه نمی‌زند.

پی نوشت: سیستم به  اسمبلی هایی که از روی ماشین یا از طریق شبکه  به اشتراک گذاشته می‌شوند اعتماد کامل میکند که این اعتماد شامل کدهای ناامن هم می‌شود ولی به طور پیش فرض به اسمبلی هایی از طریق اینترنت اجرا می‌شوند اجازه اجرای کدهای ناامن را نمی‌دهد و اگر شامل کدهای ناامن شود یکی از خطاهایی که در بالا به آن اشاره کردیم را صادر می‌کنند. در صورتی که مدیر یا کاربر سیستم اجازه اجرای آن را بدهد تمامی مسئولیت‌های این اجرا بر گردن اوست.

در این زمینه مایکروسافت ابزار سودمندی را با نام PEVerify .exe را معرفی کرده است که به بررسی تمامی متدهای یک اسمبلی پرداخته و در صورت وجود کد ناامن به شما اطلاع میدهد. بهتر است از این موضوع اطلاع داشته باشید که این ابزار نیاز دارد تا به متادیتاهای یک اسمبلی نیاز داشته باشید. باید این ابزار بتواند به تمامی ارجاعات آن دسترسی داشته باشد که در مورد عملیات بایندینگ در آینده بیشتر صحبت می‌کنیم.

IL و حقوق حق تالیف آن
بسیاری از توسعه دهندگان از اینکه IL هیچ شرایطی برای حفظ حق تالیف آن‌ها ایجاد نکرده است، ناراحت هستند. چرا که ابزارهای زیادی هستند که با انجام عملیات مهندسی معکوس می‌توانند به الگوریتم آنان دست پیدا کنند و میدانید که IL خیلی سطح پایین نیست و برگرداندن آن به شکل یک کد، کار راحت‌تری هست و بعضی ابزارها کدهای خوبی هم ارائه می‌کنند. از دست این ابزارها می‌توان به ILDisassembler و  JustDecompile اشاره کرد.
اگر علاقمند هستید این عیب را برطرف کنید، می‌توانید از ابزارهای ثالث که به ابزارهای obfuscator (یک نمونه سورس باز ) معروف هستند استفاده کنید تا با کمی پیچیدگی در متادیتاها، این مشکل را تا حدی برطرف کنند. ولی این ابزارها خیلی کامل نیستند، چرا که نباید به کامپایل کردن کار لطمه بزنند. پس اگر باز خیلی نگران این مورد هستید می‌توانید الگوریتم‌های حساس و اساسی خود را در قالب unmanaged code ارائه کنید که در بالا اشاراتی به آن کرده‌ایم.
برنامه‌های تحت وب به دلیل عدم دسترسی دیگران از امنیت کاملتری برخوردار هستند.
راهنماهای پروژه‌ها
سؤالات متداول
  • می‌خواهم برنامه‌ام را بر روی کامپیوتر مشتری بدون دردسر نصب کنم؛ با حداقل حجم و دردسر توزیع. به علاوه بدون نیاز به وصله پینه کردن اسمبلی‌های تجاری دریافت شده.

پاسخ: PdfReport از چند اسمبلی دات نتی تشکیل شده است که نیاز به نصب خاصی ندارد. همچنین حجم فشرده شده آن نیز زیر 2 مگابایت است. بنابراین از جهت توزیع مشکل خاصی نخواهید داشت. همچنین کل این مجموعه سورس باز است و مشکلات متداول همراه با گزارش سازهای تجاری را به همراه ندارد.

  • می‌خواهم فایل گزارش، به همراه برنامه و فایل exe آن و نه جدای از آن توزیع شود.

پاسخ: روش کار با PdfReport اصطلاحا code-first است. یعنی یک یا چند کلاس تهیه شده توسط شما، کار تهیه گزارش را انجام می‌دهند و تمام این‌ها کامپایل شده و به همراه فایل اجرایی یا اسمبلی‌های خاصی که برای آن درنظر می‌گیرید، کامپایل و توزیع خواهند شد. همچنین با توجه به code-first بودن آن و عدم وابستگی به فناوری خاصی، این گزارشات در برنامه‌های وب و ویندوز نیز می‌توانند بدون نیاز به تغییری در کدهای شما مورد استفاده قرار گیرند.

  • برای کار با PdfReport از کجا باید شروع کرد؟

پاسخ: لطفا برچسب PdfReport را در سایت جاری دنبال نمائید. نحوه استفاده از قابلیت‌های آن قدم به قدم توضیح داده شده‌اند.

  • می‌خواهم برای صرفه جویی در کاغذ چاپی، گزارش چند ستونه‌ای را تهیه کنم.

پاسخ: لطفا مراجعه کنید به مثال ایجاد قالب‌های سفارشی ستون‌ها.

  • می‌خواهم گزارشی را تولید کنم که حجم متن فیلدهای آن مشخص نیست. یکی ممکن است نصف صفحه باشد دیگری دو صفحه و یا بعضی تنها یک سطر.

پاسخ: در PdfReport ارتفاع هر سطر به صورت خودکار بر مبنای حجم وارد شده محاسبه و تنظیم می‌گردد. به عبارتی این تنظیم ثابت نیست و سبب حذف محتوای ارائه شده در آن‌ها یا محو شدن ردیف‌های دیگر نمی‌گردد.

  • نیاز به گزارش سازی دارم که بدون مشکل با ORMها کار کند. برای مثال در حین کار با Entity framework مستقیما بتواند با اشیاء و لیست‌های حاصل از آن کار کند.

پاسخ: یکی از انواع منابع داده تعریف شده در PdfReport جهت کار با ORMها طراحی شده است که مثالی از نحوه استفاده از آن‌را در مثال EF Code first همراه با مجموعه مثال‌های این کتابخانه می‌توانید ملاحظه نمائید.

  • آیا این کتابخانه می‌تواند از فایل سیستم (و نه صرفا بانک اطلاعاتی) هم تصاویر را دریافت و در گزارشات قرار دهد؟

پاسخ: بلی. لطفا به مثال ImageFilePath مراجعه نمائید.

  • می‌خواهم یک گزارش ساز پویا در برنامه داشته باشم. فقط کوئری غیر مشخصی را به آن بدهم و حاصل آن یک گزارش باشد.

پاسخ: امکان تهیه گزارش‌های پویا نیز در PdfReport پیش بینی شده است. توضیحات بیشتر همچنین این امکان در حین کار با ORMها نیز وجود دارد.

  • می‌خواهم بدون استفاده از بانک اطلاعاتی نیز بتوانم گزارشی را تهیه کنم. برای مثال یک لیست جنریک تشکیل شده در حافظه دارم.

پاسخ: برای این منظور تنها کافی است از منبع داده صحیحی استفاده نمائید. برای اطلاعات بیشتر به مثال IList مراجعه کنید.

  • می‌خواهم از بانک‌های اطلاعاتی دیگری بجز SQL Server استفاده کنم.

پاسخ: می‌توانید یک نمونه مثال استفاده از PdfReport را با بانک اطلاعاتی SQLite، در اینجا مشاهده کنید.

اشتراک‌ها
دلایل مهاجرت از Ruby به NET.

Ruby is, more or less, a dying language. It will probably take back off when Ruby 3.0 is released but right now, its popularity is on the decline.  

دلایل مهاجرت از Ruby به NET.
مطالب
نصب Mono 3.0 بر روی Ubuntu
با استفاده از مونو امکان اجرای برنامه‌های دات نت تحت لینوکس وجود دارند. در ادامه سعی خواهیم کرد تا نگارش 3 آن‌را بر روی اوبونتو نصب کنیم. مونو 3 تا دات نت 4 و نیم را پشتیبانی می‌کند.

دریافت اوبونتو
برای دریافت اوبونتو به آدرس ذیل مراجعه نمائید.
نسخه سرور آن GUI ندارد (هرچند بعدا در طی یک بسته 450 مگابایتی قابل نصب است). نسخه دسکتاپ آن به همراه GUI نیز هست. البته برای نصب دات نت بر روی آن این مساله تفاوتی نمی‌کند. برای نصب آزمایشی و مجازی آن هم می‌توانید برای مثال از VMWare workstation استفاده کنید؛ بدون اینکه نیاز داشته باشید این توزیع خاص لینوکس را واقعا بر روی کامپیوتر خود نصب کنید.

در تمام قسمت‌های ذیل فرض بر این است که ترمینال خط فرمان لینوکس را گشوده‌اید و همچنین سیستم به اینترنت وصل است.



دریافت Git و Curl

ابتدا دستور زیر را در خط فرمان لینوکس اجرا کنید تا سیستم بسته‌های لینوکس به روز شده و همچنین یک سری پیشنیاز مانند git ، curl و امثال آن نصب شوند (کتابخانه curl جهت استفاده در محیط‌های برنامه نویسی کاربرد دارد و همچنین برنامه پیشرفته‌ای است برای کار با وب و دریافت فایل‌ها):


 sudo apt-get update && sudo apt-get -y install git-core curl python-software-properties
sudo apt-get install build-essential automake checkinstall intltool git

نصب آخرین نگارش Mono و وابستگی‌های آن

در ادامه نوبت به نصب آخرین نگارش مونو است. از روش متداول ذیل برای نصب مونو استفاده نکنید :
 sudo apt-get install mono-complete
این دستور نگارش 2.10.8.1 را تا این تاریخ بر روی سیستم شما نصب خواهد کرد و اگر پیشتر مونو را به این روش نصب کرده‌اید، با استفاده از دستور ذیل آن‌را حذف کنید:
 sudo apt-get purge mono-runtime
برای دسترسی به آخرین نگارش نگارش مونو، نیاز است آن‌را از روی سورس آن کامپایل کنیم. اسکریپت کامل نصب آن‌را در آدرس ذیل می‌توانید پیدا کنید:
و یا اگر آدرس فوق برقرار نبود از اینجا: install_mono-3.0-sh
برای نمونه جهت نصب mono نگارش 3 از اسکریپت install_mono-3.0.sh به نحو ذیل استفاده خواهیم کرد (این دستورات را به ترتیب در ترمینال لینوکس اجرا کنید):
 mkdir mono-3.0
cd mono-3.0
wget --no-check-certificate https://github.com/nathanb/iws-snippets/raw/master/mono-install-scripts/ubuntu/install_mono-3.0.sh
chmod 755 install_mono-3.0.sh
./install_mono-3.0.sh
این پروسه مدتی طول خواهد کشید (تا تمام بسته‌های لازم از اینترنت دریافت شوند). استفاده از اسکریپت فوق کار را بسیار ساده کرده و بسیاری از مراحل لازم نصب مونو را یکجا در خود به همراه دارد. مونو 3 تا دات نت 4 و نیم را پشتیبانی می‌کند.


بعد از اجرای فرمان فوق به خطای ذیل خواهید رسید:
 config.status: error: cannot find input file: `po/mcs/Makefile.in.in'
این مورد مشکلی است که در نگارش 3.0.10 رخ داده و فراموش کرده‌اند که یک پوشه را کپی کنند (در نگارش‌های قبلی آن این مشکل وجود نداشته و با توجه به آگاه شدن از آن، در نگارش‌های بعدی نیز نباید مشکلی باشد).
برای رفع آن ابتدا به مسیر ذیل وارد شوید (پوشه build/mono-3.0.10/po)، فایل mcs را حذف (این مورد در اصل یک پوشه است و نه یک فایل) و سپس بسته اصلی mono را از github دریافت کنید. آن‌را unzip کرده و کل پوشه mcs داخل آن‌را به درون پوشه po جاری کپی کنید. سپس فایل zip دریافت شده را حذف کنید:
 cd mono-3.0/build/mono-3.0.10/po
rm mcs
wget https://github.com/mono/mono/archive/master.zip
unzip master.zip
mv mcs/ mono-3.0/build/mono-3.0.10/po
rm -rf mono-master master.zip
البته برای اینکه وقت شما زیاد تلف نشود، پوشه mcs نگارش 3.0.10 را از آدرس ذیل دریافت و پس از unzip درون پوشه mono-3.0/build/mono-3.0.10/po کپی کنید. (6 سطر فوق هم نیازی به اجرا ندارند)

پس از باز سازی پوشه مفقود mcs، باید مرحله «building mono packages» موجود در فایل install_mono-3.0.sh اجرا شود. برای این منظور، فایل final-build-mono-3.0.sh را  از آدرس ذیل دریافت و در کنار فایل install_mono-3.0.sh موجود کپی کنید.


سپس در خواص این فایل، مجوز execute را نیز فعال نمائید. اکنون آن‌را اجرا کنید:
 ./final-build-mono-3.0.sh
فایل final-build-mono-3.0.sh در حقیقت همان فایل install_mono-3.0.sh اصلی است. با این تفاوت که قسمت ابتدای فایل که در آن وابستگی‌های لازم از اینترنت دریافت می‌شدند، حذف شده است. چون پیشتر اینکار را انجام داده بودیم (با اجرای اولیه آن).


اکنون مدتی صبر کنید تا کار کامپایل نهایی تمام بسته‌های دریافت شده پس از اجرای اسکریپت final-build-mono-3.0.sh انجام شود.


آزمایش Mono نصب شده

برای اینکه مطمئن شویم، Mono درست نصب شده است، دستور زیر را در خط فرمان صادر کنید:
 /opt/mono-3.0/bin/mono -V


برای اینکه این مسیر را به Path لینوکس اضافه کنیم تا قادر شویم فرمان mono را در هر مسیری اجرا کنیم، ابتدا دستور ذیل را اجرا کرده
 sudo nano /etc/environment
و سپس در ادیتور باز شده، مسیر و عبارات ذیل را به انتهای مقدار جاری اضافه کنید:
 :/opt/mono-3.0/bin


بعد ctrl+x را زده، به پیام ذخیره سازی تغییرات پاسخ مثبت دهید. سپس نیاز است یکبار logoff و login کنید تا این تغییرات اعمال شوند.


یک نکته تکمیلی:
اگر به صفحه نگارش‌های رسمی Mono 3.x مراجعه کنید، نگارش‌های جدیدتری را نیز می‌توانید ملاحظه کنید. فایل‌های قابل نصب آن‌ها نیر در آدرس‌های ذیل قرار دارند:
برای استفاده از اسکریپت install_mono-3.0.sh با این نگارش‌های جدیدتر فقط کافی است تعاریف ذیل را بر اساس شماره نگارش بسته‌های جدید اصلاح کنید:
PACKAGES=("mono-3.0.10"
"libgdiplus-2.10.9"
"gtk-sharp-2.12.11"
"xsp-2.10.2"
"mod_mono-2.10")

URLS=("http://download.mono-project.com/sources/mono/mono-3.0.10.tar.bz2"
"http://download.mono-project.com/sources/libgdiplus/libgdiplus-2.10.9.tar.bz2"
"http://download.mono-project.com/sources/gtk-sharp212/gtk-sharp-2.12.11.tar.bz2"
"http://download.mono-project.com/sources/xsp/xsp-2.10.2.tar.bz2"
"http://download.mono-project.com/sources/mod_mono/mod_mono-2.10.tar.bz2")