مطالب
آشنایی با CLR: قسمت سیزدهم
ترکیب ماژول‌ها به قالب یک اسمبلی
فایل Program.exe یک فایل PE با جداول متادیتا است که همچنین یک اسمبلی هم می‌باشد. یک اسمبلی مجموعه‌ای از یک یا چند فایل، شامل تعاریف نوع و منابع (ریسورس) می‌باشد و یکی از فایل‌های اسمبلی، برای نگهداری manifest انتخاب می‌شود. این جدول مجموعه‌ای است از جداول متادیتا که به طور کلی شامل نام فایل‌هایی است که قسمتی از اسمبلی را تشکیل می‌دهند. برای همین گفتیم که CLR با اسمبلی‌ها کار می‌کند. ابتدا جداول manifest را خوانده تا نام فایل‌ها را شناسایی کرده تا از آن‌ها را به حافظه بارگزاری کند. اسمبلی‌ها چند خصوصیت دارند که باید آن‌ها را بدانید:
- نوع‌های با قابلیت استفاده‌ی مجدد را تعریف می‌کنند.
- داری شماره‌ی نسخه version هستند.
- می‌توانند شامل اطلاعات امنیتی باشند.
این خواصی است که یک اسمبلی به همراه دارد و فایل‌هایی که شامل می‌شود، نمی‌توانند چنین خاصیتی را داشته باشند؛ مگر اینکه آن فایل‌ها در متای خود جدول manifest داشته باشند.
شما برای بسته بندی، شماره نسخه، مباحث امنیتی و استفاده از نوع‌ها، باید آن‌ها را داخل ماژولی قرار دهید که جزئی از اسمبلی است. یک فایل اسمبلی  همانند program.exe به عنوان یک فایل واحد شناخته می‌شود. با اینکه یک اسمبلی از چند فایل تشکیل می‌شود، فایل‌های PE به همراه جداول متادیتای آن و تعدادی ریسورس مثل فایل‌های gif و jpg است که به شما کمک می‌کند به همه‌ی آن‌ها به عنوان یک فایل منطقی EXE یا dll نگاه کنید.
یکی از دلایلی که در قسمت سوم گفتیم این بود که می‌توانیم فایل‌هایی را که به ندرت استفاده می‌شوند، از طریق اینترنت مورد استفاده قرار دهیم. در حالتیکه نیاز به دسترسی به اسمبلی‌های روی اینترنت دارید، CLR ابتدا کش را بررسی می‌کند تا آیا فایل حاضر است یا خیر؟ اگر پاسخ مثبت بود، در حافظه قرار می‌گیرد. ولی اگر پاسخ منفی بود، CLR به آدرسی که اسمبلی در آن قرار دارد، رجوع کرده و آن را دانلود می‌کند و اگر فایل مد نظر یافت نشد، استثنای FileNotFound  را در حین اجرا صادر خواهد کرد.
آقای جفری ریچر در کتاب خود سه تا از دلایل استفاده‌ی از اسمبلی‌های چند فایله را بر می‌شمارد:
  • جداسازی نوع‌ها در فایل‌های جداگانه که باعث کاهش حجم فایل از طریق اینترنت و بارگزاری حجم کمتر در حافظه  می‌شوند.
  • استفاده از فایل‌های منبع و داده‌ها در اسمبلی: فرض کنید نیاز به محاسبه‌ی اطلاعات بیمه دارید و برای این کار به اطلاعات داخل یک جدول آماری احتیاج دارید. این جدول آماری می‌تواند یک فایل متنی ساده یا یک صفحه‌ی گسترده مثل اکسل یا در قالب ورد و هر چیز دیگری باشد که به جای embed شدن این جداول در سورس کد برنامه، آن‌ها را با استفاده از ابزاری مثل Assembly Linker -AL.exe می‌توانید جزئی از اسمبلی کنید و فقط نیاز است که بدانید چگونه آن فایل را پارس یا تبدیل کنید.
  • استفاده از انواع ایجاد شده در زبان‌های مختلف. در این حالت شما مقداری از کد را با استفاده از #C نوشته اید و مقداری از آن را با Visual Basic می‌نویسید و هر کدام در نهایت به یک ماژول جداگانه کامپایل خواهند شد. ولی تبدیل آن به یک واحد منطقی مثل اسمبلی ممکن است و از این نظر می‌توانید روی ماژول‌های یک دسته کنترل داشته باشید.
اگر چندین نوع دارید که شامل نسخه بندی و تنظیمات امنیتی مشترک هستند، بهتر است در یک اسمبلی قرار گیرند تا اینکه در اسمبلی‌های جداگانه‌ایی قرار بگیرند. دلیل این کار هم ایجاد performance یا کارآیی بهتر است. بارگذاری یک  اسمبلی در حافظه زمانی را برای یافتن آن از CLR و ویندوز می‌گیرد و سپس وارد بارگیری آن‌ها در حافظه و آماده سازی می‌شود. پس هر چه تعداد اسمبلی‌ها کمتر باشد، کارآیی بهتری خواهید داشت، چون کمتر شدن بارگیری برابر با کاهش  صفحات کاری است و پراکندگی fragmentation فضای آدرس دهی آن فرایند را کاهش خواهد داد. نهایتا Ngen می‌تواند در بهینه سازی فایل‌های بزرگتر موفق باشد.
برای ساخت اسمبلی، باید یکی از فایل‌های PE را برای نگهداری جدول manifest انتخاب کنید؛ یا خودتان یک فایل PE جدا درست کنید که تنها شامل جدول مانیفست شود. جدول زیر قالبی از جداول مانیفست هست که بابت ماژول‌های اضافه شده به یک اسمبلی ایجاد می‌شوند.
 AssemblyDef  شامل مدخل ورودی (آدرس شروع حافظه) برای اسمبلی‌هایی است که ماژول عضو آن است. این مدخل شامل نام اسمبلی (بدون مسیر و پسوند)، شماره نسخه یا ورژن، culture، فلگ، الگوریتم هش و کلید عمومی ناشر، که می‌تواند نال باشد، هست.
 FileDef  شامل یک مدخل ورودی برای هر فایل PE و فایل‌های ریسورسی است که قسمتی از اسمبلی را تشکیل می‌دهند. این مدخل ورودی شامل نام و پسوند فایل (بدون ذکر مسیر)، فلگ و مقدار هش می‌شود. اگر تنها یک اسمبلی وجود داشته باشد، این جدول هیچ مدخلی نخواهد داشت.
 ManifestResourceDef  شامل یک مدخل ورودی برای هر فایل ریسورس است. این مدخل شامل نام فایل ریسورس، فلگ و یک اندیس به جدول FileDef است که در آن اشاره‌ای به آن فایل ریسورس یا استریم است.
 ExportedTypesDef  شامل یک مدخل ورودی برای هر نوع عمومی است که از همه ماژول‌های PE استخراج شده است. هر مدخل شامل نام نوع و اندیسی به جدول FileDef و یک اندیس دیگر به جدول TypeDef است. نکته: برای ذخیره سازی حافظه و کم حجم شدن فایل‌ها، نوع‌های استخراج شده از فایلی که شامل مانیفست است دیگر در جدول جاری نام نوع‌ها ذکر نمی‌گردد؛ چرا که این اطلاعات در جدول TypeDef اسمبلی جاری موجود است.
  نکته: اسمبلی که شامل مانیفست است، شامل یک جدول AssemblyRef نیز می‌گردد که به تمام اسمبلی‌های ارجاع شده در آن اسمبلی اشاره می‌کند. با استفاده از ابزارهای موجود می‌توان اسمبلی مدنظر را باز کرده و به این ترتیب لیستی از اسمبلی‌های ارجاع شده را خواهید دید و بدین صورت این اسمبلی یک اسمبلی خود تعریف می‌شود.

کامپایلر سی شارپ با استفاده از سوئیچ‌های زیر یک اسمبلی را تولید می‌کند:
/t[arget]:exe, /t[arget]:winexe, /t[arget]: appcontainerexe, /t[arget]: library, or /t[arget]:winmdobj

سوئئیچ‌های بالا باعث می‌شود که یک فایل PE با جدول مانیفست تولید گردد. در صورتیکه سوئیچ زیر را به کار ببرید، فایل تولید شده شامل جدول مانیفست نمی‌شود.
/t[arget]:module
این فایل PE تولید شده در قالب یک dll است که باید قبل از اینکه CLR به نوع‌های داخل آن دسترسی پیدا کند، به یک اسمبلی اضافه گردد. موقعی‌که شما از سوئیچ بالا استفاده می‌کنید، کامپایلر سی شارپ به طور پیش فرض از پسوند netmodule برای فایل خروجی استفاده می‌کند.

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


مطالب
معرفی چهار افزودنی رایگان Visual Studio.NET

توسط این ابزار متدهای شما به ترتیب حروف الفباء مرتب شده و همچنین متدهای عمومی و خصوصی در region های مخصوص خود به صورت خودکار قرار خواهند گرفت.


نحوه عملکرد آنرا در اینجا مشاهده نمائید.

این افزودنی در حقیقت یک افزودنی جهت ReSharper به‌شمار می‌رود و کار آن بررسی اصول نامگذاری صحیح متغیرها، توابع و امثال آن است. همچنین کار غلط گیری املایی را نیز انجام می‌دهد.



تیم‌های داخلی مایکروسافت از این ابزار برای یک دست سازی سورس‌های تیم‌های مختلف استفاده می‌کنند.
هرچند عده‌ای این قوانین را بیش از اندازه سخت گیرانه می‌دانند!


همچنین اگر علاقمند باشید که StyleCop را به صورت خودکار و در زمان تایپ سورس استفاده کنید (حالت فعلی آن به صورت دستی است و باید برای مثال بر روی صفحه کلیک راست کرد و از منوی ظاهر شده گزینه مربوطه را انتخاب و اجرا نمود)، افزودنی دیگری برای ReSharper طراحی شده است که اینکار را برای شما انجام می‌دهد:
http://www.codeplex.com/StyleCopForReSharper/

اگر هم تمایل به غیر فعال کردن افزودنی‌های ReSharper را داشتید، می‌توان به منوی مربوطه در VS.Net مراجعه کرد و آنها را غیرفعال نمود (ReSharper->plugins).


نظرات نظرسنجی‌ها
آیا با وجود سی‌ام‌اس فروشگاهی قدرتمندی مثل nopCommerce یا SmartStore آیا منطقی است که ما دوباره خودمان از صفر کد بزنیم؟
نکته بسیار مهم :
هر ابزاری برای هر کاری مناسب نیست. هر دو موردی که در نظر سنجی نام برده شده راه کارهای سطح متوسط در ecommerce محسوب می‌شوند. بهتر بود نظر سنجی را به صورت چند انتخابی طراحی می‌کردید.
طبیعتا هزینه تمام شده نقش مهمی در کسب موفقیت در این زمینه دارد. نوشتن یک بستر جامع ecommerce کاری بسیار پر هزینه است. نمونه‌های موجود ایرانی و خارجی که از صفر نوشته شده اند حداکثر در حد متوسط قرار می‌گیرند.
اگر قصد شما داشتن چیزی مثل دیجیکالا است و چنان برنامه و بودجه ای دارید نوشتن از صفر یا توسعه یک CMS پیشرفته گزینه مناسبی است. ولی اگر شمار فروشنده ecommerce هستید و خدمات آن را ارائه می‌دهید تعداد مشتریانی که از شما کار سفارشی بخواهند خیلی کم است و بیشتر کسب و کار‌ها نیاز به یک راه کار آماده ماژولار دارند و بودجه آنها در همین حد آنها را متوقف می‌کند.
با تجربه ای که در ecommerce‌های مختلف داشته ام (PHP و ASP.NET) در مقیاس‌های کوچک، متوسط ، بزرگ و خیلی بزرگ به شما پیشنهاد می‌کنم هر ابزاری را برای کاربرد مناسب انتخاب کنید. هیچ CMS همه کاره ای برای همه پروژه‌ها وجود ندارد.
کلمه قدرتمند! یک کلمه فنی نیست، بیشتر به درد بازاریابی می‌خورد. nopcommerce در حد برداشتن یک سنگ متوسط قدرتمند است. نه برای یک فروشگاه چند منظوره بین المللی با عملیات تجاری سنگین.
نظرات مطالب
یکدست کردن «ی» و «ک» در ASP.NET Core با پیاده‌سازی یک Model Binder سفارشی
با حذف قسمت [FromBody] از امضای اکشن متد زیر : 
public IActionResult Create([FromBody] CreateViewModel vm)
{
باز هم نال برگردوند مدل رو از سمت ویو وقتی این Annotation رو قرار میدم بالای viewmodel.
این هم ViewModel بنده :
[ModelBinder(BinderType = typeof(PersianDateModelBinder))]
public partial class CreateViewModel
 {
        public int Id { get; set; }
        [DisplayName("عنوان مطلب")]
        public string Title { get; set; }
        [DisplayName("نگارش مطلب")]
        public string Content { get; set; }
        [DisplayName("تاریخ درج")]
        public DateTime CreateDate { get; set; } = DateTime.Now.Date;
        [DisplayName("تاریخ انتشار")]
        public DateTime PublishDate { get; set; } = DateTime.Now.Date;
        
 }
این دو تا تاریخ رو هم (CreateDate و PublishDate) هم در همان viewModel مقدار دهی اولیه کردم (البته نمیدونم این کار اینجا درست هستش یا نه) که اگه کاربر از داخل PersianDatePicker انتخاب نکرد تاریخ امروز رو بفرسته.
نظرات مطالب
آشنایی با الگوی M-V-VM‌ - قسمت دوم
- بله. اینجا یک بررسی نال بودن آیتم انتخاب شده باید قبل از کم و زیاد کردن مقادیر اضافه شود.
- دو breakpoint داخل هر دو متد CanExecute موجود قرار دهید. خواهید دید که به ازای هر بار کلیک بر روی دکمه‌های متناظر (افزایش یا کاهش)، متد CanExecute مرتبط هم در ابتدا یکبار فراخوانی می‌شود.
- غیرفعال کردن خودکار دکمه را من در این مثال ابتدایی پیاده سازی نکردم و مرتبط است با EventHandler تعریف شده‌ای به نام CanExecuteChanged. اگر CanExecuteChanged در متدهای CanExecute صدا زده شود این غیر فعال سازی هم رخ خواهد داد.
این مثال رو بر اساس توضیحات ذکر شده به روز کردم و از اینجا قابل دریافت است:
http://www.box.net/shared/zc27lmyvku

+ کلا در مورد روش‌های بهتر Model Validation در قسمت پنجم بیشتر بحث شده است. همچنین در قسمت‌های بعد این کلاس‌های خام مشتق شده از ICommand با نمونه‌های بهتر جایگزین می‌شوند (DelegateCommand و یا RelayCommand).
مطالب
نکات استفاده از افزونه‌ی Web Essentials جهت کار با تصاویر
در این مطلب نکات کار با تصاویر را توسط افزونه‌ی Web Esstentials بررسی می‌کنیم. این افزونه قابلیت‌های زیر را در کار با تصاویر در اختیار شما قرار می‌دهد:
بهینه‌سازی تصاویر
یکی از موارد مهمی که باید مورد توجه قرار بگیرد، استفاده از تصاویر کم حجم در وب‌سایت می‌باشد. روش‌های مختلفی جهت بهینه‌سازی تصاویر مورد استفاده در سایت وجود دارند، به طور مثال جهت بهینه‌سازی تصاویر PNG می‌توانید از ابزار PNGGauntlet استفاده کنید. همچنین اینجا نیز یک ابزار آنلاین موجود می‌باشد. افزونه‌ی Web Essentails این قابلیت را به آسانی در اختیار شما قرار می‌دهد؛ اینکار را می‌توانید توسط این افزونه به روش‌های زیر انجام دهید:
  • کلیک راست بر روی تصویر
برای اینکار بر روی فایلی که می‌خواهید optimize کنید، کلیک راست کرده و از منوی ظاهر شده گزینه Web Essentials و سپس Optimize Image را انتخاب کنید:

در قسمت status bar نیز می‌توانید نتیجه را مشاهده کنید:

  • انتخاب چندین تصویر
روال قبلی را می‌توانید برای چندین فایل انتخاب شده و یا یک پوشه تکرار کنید:

  • بهینه‌سازی تصاویر موجود در فایل‌های CSS
همچنین امکان بهینه‌سازی تصاویر داخل فایل‌های CSS نیز توسط این افزونه امکان پذیر است:

  • بهینه سازی تصاویر Base64 Encode
توسط این افزونه می‌توانیم تصاویر  Data Uri  را نیز بهینه سازی کنیم:

همانطور که در تصویر فوق مشاهده می‌کنید می‌توانیم تصاویری که به صورت Data Uri درون کد پیوست شده اند را با کلیک بر روی Save to file به صورت یک فایل ذخیره کنیم.

ایجاد تصاویر Sprite
یکی دیگر ار قابلیت‌های افزونه Web Essentials امکان تهیه تصاویر به صورت Sprite می باشد. برای اینکار کافی است به این صورت عمل کنید:

بعد از کلیک بر روی Create image sprite باید یک نام برای آن تعیین کنید و سپس بر روی کلید Save کلیک کنید. با اینکار یک فایل از نوع XML با پسوند sprite برای شما ساخته خواهد شد:
<?xml version="1.0" encoding="utf-8"?>
<sprite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://vswebessentials.com/schemas/v1/sprite.xsd">
  <settings>
    <!--Determines if the sprite image should be automatically optimized after creation/update.-->
    <optimize>true</optimize>
    <!--Determines the orientation of images to form this sprite. The value must be vertical or horizontal.-->
    <orientation>vertical</orientation>
    <!--File extension of sprite image.-->
    <outputType>png</outputType>
    <!--Determin whether to generate/re-generate this sprite on building the solution.-->
    <runOnBuild>false</runOnBuild>
    <!--Use full path to generate unique class or mixin name in CSS, LESS and SASS files. Consider disabling this if you want class names to be filename only.-->
    <fullPathForIdentifierName>true</fullPathForIdentifierName>
    <!--Use absolute path in the generated CSS-like files. By default, the URLs are relative to sprite image file (and the location of CSS, LESS and SCSS).-->
    <useAbsoluteUrl>false</useAbsoluteUrl>
    <!--Specifies a custom subfolder to save CSS files to. By default, compiled output will be placed in the same folder and nested under the original file.-->
    <outputDirectoryForCss />
    <!--Specifies a custom subfolder to save LESS files to. By default, compiled output will be placed in the same folder and nested under the original file.-->
    <outputDirectoryForLess />
    <!--Specifies a custom subfolder to save SCSS files to. By default, compiled output will be placed in the same folder and nested under the original file.-->
    <outputDirectoryForScss />
  </settings>
  <!--The order of the <file> elements determines the order of the images in the sprite.-->
  <files>
    <file>/Content/Images/01.png</file>
    <file>/Content/Images/02.png</file>
    <file>/Content/Images/03.png</file>
    <file>/Content/Images/04.png</file>
  </files>
</sprite>
یکی از زیر مجموعه‌های این فایل، تصویر نهایی می‌باشد، همچنین فایل‌های css, less, map و scss آن نیز تولید می‌شود:

به عنوان مثال فایل CSS تصویر فوق به صورت زیر می‌باشد:
/*
This is an example of how to use the image sprite in your own CSS files
*/
.Content-Images-01 {
/* You may have to set 'display: block' */
width: 32px;
height: 32px;
background: url('icons.png') 0 0;
}
.Content-Images-02 {
/* You may have to set 'display: block' */
width: 32px;
height: 32px;
background: url('icons.png') 0 -32px;
}
.Content-Images-03 {
/* You may have to set 'display: block' */
width: 32px;
height: 32px;
background: url('icons.png') 0 -64px;
}
.Content-Images-04 {
/* You may have to set 'display: block' */
width: 32px;
height: 32px;
background: url('icons.png') 0 -96px;
}
هر کدام از کلاس‌های فوق به یک تصویر در فایل مربوطه توسط image position اشاره می‌کند. شما می‌توانید با انتساب هر کدام از کلاس‌های فوق به یک المنت از آن تصویر استفاده نمائید:
<div class="Content-Images-01"></div>
<div class="Content-Images-02"></div>
<div class="Content-Images-03"></div>
<div class="Content-Images-04"></div>

استفاده از تصاویر Data URIs
یکی دیگر از روش‌های کاهش درخواست‌های HTTP در یک سایت استفاده از Data URIs  می باشد، توسط این روش می‌توانید فایل هایتان را درون HTML و یا CSS قرار دهید یا به اصطلاح embed کنید. به طور مثال جهت استفاده از یک تصویر می‌توانید به راحتی با آدرس دهی تصویر درون تگ img، تصویر را درون صفحه نمایش دهید:
<img src="https://www.dntips.ir/images/logo.png" />

همین کار را می‌توانیم توسط Data URIs انجام دهیم:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC" />
در کد فوق تصویر موردنظر را درون HTML به صورت embed شده قرار داده ایم، در این حالت دیگری نیازی به رفت و برگشت به سرور جهت نمایش تصویر نیست.
سینتکس Data URIs
به طور مثال تگ زیر را در نظر داشته باشید:
<img src="data:image/png;base64,iVBOR..." />
مقدار ویژگی src شامل موارد زیر است:
data: نام schema
image/png: نوع محتوا(content type)
base64: نوع encoding استفاده شده برای encode کردن اطلاعات
iVBOR...: اطلاعات encode شده.
توسط افزونه Web Essentials به راحتی می‌توانید تصویر موردنظرتان را به صورت Data URI تهیه کنید: