فایل program.exe محصول مثال مطلب ساخت اسمبلی مدیریت شده، چیزی بیشتر از یه فایل PE به همراه یکسری داده های اضافه مثل جداول متادیتاست. این فایل تو تعریفی پیشرفته تر، یه «اسمبلی» هست. این جداسازی تعریف و متمایز کردنش یعنی چی؟ خب پس اول به تعریف دقیقتر از یه اسمبلی آورده میشه.
یه اسمبلی درواقع مجموعه ای از «یک یا چند فایل» شامل تعاریف نوع ها و اعضاشون، اطلاعات گوناگون موردنیاز سیستم عامل و CLR، داده های قسمت های مختلف اسمبلی (متادیتا) و همچنین درصورت وجود فایلهای منبع (resource) هست.
اما نکته ای که اینجا باید بهش دقت کرد اینه که:
یکی از فایلهای اسمبلی برای ذخیره و نگهداری داده های جداول مانیفست انتخاب میشه. به عبارت دیگه، اگه اسمبلی تک فایله باشه، مانیفست تو همین یه فایل ذخیره میشه، ولی اگه اسمبلی چند فایله باشه، تنها یکی از این فایلها (فایل اصلی اسمبلی) داده های مانیفست رو میزبانی میکنه!
مانیفست، یکی دیگه از دسته های جداول متایتاست که عمدتا برای نگهداری نام فایلهایی که اسمبلی رو تشکیل میدن استفاده میشه. علاوه بر این، این جدولها حاوی داده هایی مثل نسخه اسمبلی، فرهنگ یا کالچر، تولید یا توزیع کننده اسمبلی، نوع های با دسترسی عمومی نیز هستن.
هنگامیکه CLR میخواد با یه اسمبلی (مخصوصا چند فایله) کار کنه، ابتدا فایلی از اسمبلی که حاوی مانیفسته رو بارگذاری میکنه، سپس با استفاده از داده های مانیفست، نام سایر فایلهای اسمبلی رو بدست میاره و اونا رو تو گام بعدی درصورت نیاز! بارگذاری میکنه.
برای روشنتر شدن موضوع، مشخصات کلی یه اسمبلی بصورت زیر آورده شده:
- یه اسمبلی نوع هایی با قابلیت استفاده دوباره (reusable types) تعریف میکنه.
- یه اسمبلی یه ویژگی به نام شماره نسخه داره.
- یه اسمبلی میتونه یکسری مشخصات و داده های امنیتی مرتبط داشته باشه.
اما نکته ای درباره مشخصات این چنینی اسمبلی باید اشاره بشه اینه که تو همه فایلهای تشکیل دهنده اسمبلی، این اطلاعات ذخیره نمیشه. این داده ها به همراه برخی اطلاعات دیگه تو مانیفست اسمبلی ذخیره میشه و همونطور که قبلا هم اشاره شد، مانیفست فقط تو «فایل اصلی» اسمبلی نگهداری میشه.
برای استفاده از یه اسمبلی، باید مشخصات اشاره شده درباره اسمبلی رو تو ماژولهایی که اسمبلی رو تشکیل میدن قرار داد. تو بیشتر موارد یه اسمبلی فقط از یه فایل تشکیل شده، مثل مثال program.exe. اما یه اسمبلی میتونه از چند فایل هم تشکیل بشه (معروف به اسمبلی های چند فایله یا Multifile Assembly):
- چند فایل PE یا ماژول حاوی متادیتا
- و چند فایل منبع (resource) مثل تصاویر یا فایلهای ریسورس (resx.).
البته بصورت ساده میشه اسمبلی رو یه فایل exe. یا dll. قملداد کرد. اطلاعات بیشتر راجع به اسمبلی های چند فایله: ! و !.
استفاده از اسمبلی های چندفایله به جای تک فایله، مزایا و دلایل مختلفی داره که مهمترین دلایلش عبارتنداز:
- با اینکار میشه نوع های تعریف شده رو تو چند فایل مختلف طبقه بندی کرد. بدین ترتیب تنها قسمتهایی از برنامه که نیازه یا مجازه! منتشر یا مثلا از طریق اینترنت دانلود میشه. بنابراین هم میشه کارایی و سرعت بالاتری در اجرای برنامه ها داشت (فقط اون قسمتهایی از برنامه که نیازه، دانلود یا بارگذاری میشه)، و هم میشه کنترل بیشتری روی قسمتهای قابل اجرای برنامه داشت (فقط قسمتهایی از برنامه که مجازه یا مثلا هزینه استفاده از اون پرداخت شده، نصب و اجرا بشه).
- با اینکار میشه فایلهای منابع یا داده خاصی رو به اسمبلی اضافه کرد. مثلا اگه برنامه ما نیاز به استفاده از یکسری داده های خاص آماری برای انجام محاسبات نیاز داره، میشه این داده های خاص و ثابت رو به جای پیاده سازی مستقیم تو کد، به صورت فایل داده به قسمت منابع اسمبلی اضافه کرد و با استفاده از امکانات فراهم شده به اونا دسترسی پیدا کرد. برای افزودن این فایلهای داده و منبع به اسمبلی میشه از ابزارهای موجود (مثل AL.exe یا Assembly Linker) استفاده کرد تا این داده ها رو بصورت بخشی از اسمبلی نهایی درآورد. درضمن فرمت ذخیره این فایل داده ها میتونه هرجوری باشه، مثل text یا excel یا هرچیزه دیگه. البته بشرطی که برنامه چگونگی استخراج داده ها از فرمت فایل مربوطه رو بدونه!
- با اینکار میشه اسمبلی هایی داشت که قسمتهای مختلف اون با زبانهای برنامه نویسی مختلفی تولید شدن. مثلا میشه برخی از نوع های اسمبلی رو با #C و برخی دیگه رو با VB.NET و بقیه رو با #F نوشت. سپس با استفاده از کامپایلرهای مربوطه، ماژول IL هر بخش تولید شده و در نهایت میشه با استفاده از ابزار خاصی (مثل Assembly Linker) این ماژولها رو به هم وصل و یه اسمبلی تشکیل داد. از نظر استفاده کنندگان این اسمبلی، فرقی نمیکنه که همه قسمتهای اون با یه زبان برنامه نویسی و بصورت عادی تولید شده یا بدین صورت و با استفاده از چند زبان مختلف. استفاده کننده درنهایت فقط نوع های پیاده شده تو اسمبلی رو میبینه و از اونا استفاده میکنه.
البته همیشه هم استفاده از اسمبلی های چندفایله مناسب نیست. مثلا اگه نوع های تعریف شده میتونن تو یه واحد با نسخه و تنظیمات امنیتی یکسانی قرار بگیرن، جداسازی اونا توجیهی نداره و بهتره همه رو تو یه فایل و بصورت یه اسمبلی تک فایله پیاده کرد. دلیل اصلی، کارایی اجراست. بارگذاری یه فایل یا اسمبلی زمان میبره. چون CLR و ویندوز باید فایل مربوطه رو پیدا، بارگذاری کرده و عملیات آغاز بکار رو درموردش انجام بدن. بنابراین اگه قرار باشه همه نوع ها بارگذاری و استفاده بشن، بنابراین وجود تعداد فایل یا اسمبلی کمتر میتونه باعث افزایش قابل ملاحظه سرعت و کارایی برنامه بشه.
در ادامه جداول مانفیست که یه ماژول مدیریت شده رو به یه اسمبلی تبدیل میکنن آورده شده:
1 - AssemblyDef
اگه ماژول جاری یه اسمبلی رو تعریف بکنه، این جدول شامل یه ورودی تنهاست. این ورودی شامل:
- نام اسمبلی (بدون پسوند و مسیر اون)
- نسخه اسمبلی (major, minor, build و revision)
- کالچر
- فلگها
- الگوریتم هش
- و کلید عمومی اسمبلی در صورت وجود
است.
2 - FileDef
برای هر فایل تشکیل دهنده اسمبلی (البته بغیر از فایل اصلی اسمبلی که تو جدول AssemblyDef براش یه ورودی درج میشه) یه ورودی تو این جدول ثبت میشه. این ورودیها شامل:شامل یه ورودی برای همه نوع های عمومی تعریف شده تو تمام ماژولهای اسمبلی هست. بخش های این ورودی عبارتنداز:
- نام نوع
- یه ایندکس به جدول FileDef برای معرفی فایلی که حاوی پیاده سازی نوع مربوطه هست
- و یه ایندکس به جدول تعریف TypeDef از جداول متادیتای اسمبلی
نکته: نوع هایی که تو خود ماژول اصلی اسمبلی تعریف شدن، دیگه تو این جدول تکرار نمیشن و فقط تو همون جدول تعریف TypeDef آورده میشن. اینکار برای صرفه جویی و کاهش حجم اسمبلی انجام میشه.
4 - ManifestResourceDef
.: . :.