مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 16 - کار با Sessions
سشن‌ها نیز همانند تمام قسمت‌های دیگر یک برنامه‌ی ASP.NET Core، به صورت پیش فرض غیرفعال هستند و نیاز به مراحل خاصی است تا امکان استفاده‌ی از آن‌ها فراهم شود. همچنین روش کار کردن با آن‌ها نیز متفاوت است با نگارش‌های قبلی ASP.NET (تمام نگارش‌ها).


سشن چیست؟

شیء سشن، مجموعه‌ای از اشیاء serialized مرتبط با جلسه‌ی کاری جاری یک کاربر است. این اشیاء عموما در حافظه‌ی محلی سرور ذخیره می‌شوند؛ اما امکان ذخیره سازی توزیع شده‌ی آن‌ها در بانک‌های اطلاعاتی نیز پیش بینی شده‌است.
عموما استفاده‌ی از اشیاء سشن توصیه نمی‌شوند. از این جهت که این نوع اشیاء بسیار شبیه هستند به متغیرهای سراسری و وجود این نوع متغیرها اساسا ضعف طراحی شیء‌گرا به حساب می‌آیند. اما با توجه به ماهیت stateless بودن برنامه‌های وب، به این معنا که با پایان رندر یک صفحه، تمام اشیاء مرتبط با آن‌ها نیز در سمت سرور تخریب می‌شوند، نیاز است برای یک سری از داده‌های عمومی کاربر، راه حلی را پیدا کرد تا بتوان از اطلاعات آن‌ها استفاده‌ی مجدد کرد. برای مثال نگهداری رشته‌ی اتصالی بانک اطلاعاتی که کاربر در حین لاگین به سیستم آن‌را انتخاب کرده‌است (اگر برنامه به ازای هر سال از یک بانک اطلاعاتی مجزا استفاده می‌کند) و یا زمانیکه کاربری captcha را پر می‌کند و مقدار آن‌را به سمت سرور ارسال می‌کند، نیاز است مقدار ارسالی او را با مقدار ابتدایی captcha مقایسه کرد. یک چنین اطلاعاتی نباید با پایان رندر صفحه تخریب شوند و نیاز است تا زمانیکه جلسه‌ی کاری کاربر به پایان نرسیده‌است، در دسترس باشند. به همین جهت است که مفهومی را به نام «اشیاء سشن» طراحی کرده‌اند.
درکل خارج از این موارد بهتر است از سشن استفاده نکنید و در جای جای برنامه‌ی خود ردپای آن‌را باقی نگذارید و به خاطر داشته باشید:
متغیر سشن = متغیر سراسری = ضعف طراحی شی‌‌ءگرا


توصیه‌ی به استفاده‌ی از روش‌های سبک وزن‌تر

سشن‌ها تنها روش به اشتراک گذاری اطلاعات نیستند. اگر می‌خواهید اطلاعاتی را در بین میان افزارهای برنامه در طی یک درخواست به اشتراک بگذارید، شاید سشن هم یک راه حل باشد؛ اما راه حلی سنگین وزن. راه حل بهتر برای این موارد، استفاده‌ی از HttpContext.Items است. HttpContext.Items نیز همانند سشن، یک key/value store است؛ اما طول عمر آن محدود است به طول عمر درخواست جاری و در تمام میان افزارهای برنامه در دسترس است.
برای مثال در یک میان افزار آن‌را تنظیم می‌کنید:
app.Use(async (context, next) =>
{
   context.Items["isVerified"] = true;
   await next.Invoke();
});
و سپس در میان افزاری دیگر از آن استفاده خواهید کرد:
app.Run(async (context) =>
{
   await context.Response.WriteAsync("Verified request? " + context.Items["isVerified"]);
});


فعال سازی سشن‌ها در ASP.NET Core

ASP.NET Core یک choose-what-you-need framework است. به این معنا که تا زمانیکه قابلیتی را به صورت صریح فعال سازی نکرده باشید، در دسترس نخواهد بود. همین مساله در نهایت به کاهش مصرف منابع این نوع برنامه‌ها و همچنین طراحی ماژولار سیستم ختم می‌شوند. برای مثال در نگارش‌های قبلی ASP.NET (تمام نگارش‌ها)، سشن‌ها به صورت پیش فرض فعال هستند، مگر آنکه HTTP Module آن‌را در فایل web.config حذف کنید؛ اما در اینجا برعکس است.
اگر تنها در موارد خاصی که ذکر شد، نیاز به استفاده‌ی از متغیرهای سشن را داشتید، روش فعال سازی آن به صورت ذیل است:
الف) نصب بسته‌ی نیوگت Microsoft.AspNetCore.Session
برای این منظور وابستگی ذیل را به فایل project.json اضافه کنید:
{
    "dependencies": {
      //same as before
      "Microsoft.AspNetCore.Session": "1.0.0"
    }
}
ب) انجام تنظیمات آغازین برنامه
برای این کار به کلاس آغازین برنامه مراجعه کرده و ابتدا سرویس سشن‌ها را فعال کنید:
public void ConfigureServices(IServiceCollection services)
{
    services.AddSession();
و سپس در متد Configure، استفاده‌ی از سشن‌ها را نیز باید ذکر کنید:
public void Configure(IApplicationBuilder app)
{
    app.UseSession();
در اینجا امکان سفارشی سازی مقادیر پیش فرض مدیریت سشن‌ها نیز وجود دارند. برای مثال زمان پیش فرض انقضای سشن کاربر، پس از 20 دقیقه عدم فعالیت او است که قابل تغییر می‌باشد:
app.UseSession(options: new SessionOptions
{
    IdleTimeout = TimeSpan.FromMinutes(30),
    CookieName = ".MyApplication"
});


روش استفاده‌ی از سشن‌ها

در مثال ذیل نحوه‌ی ذخیره سازی اطلاعات را در شیء سشن جلسه‌ی جاری یک کاربر، ملاحظه می‌کنید:
public ActionResult TestSession()
{
 
   this.HttpContext.Session.Set("key-1", BitConverter.GetBytes(DateTime.Now.Ticks));
   this.HttpContext.Session.SetInt32("key-2", 1);
   this.HttpContext.Session.SetString("key-3", "DNT");
 
   return Content("OK!");
}
به همراه نحوه‌ی بازیابی این اطلاعات در متدهای دیگر برنامه:
 public IActionResult Index()
{
   byte[] key1 = this.HttpContext.Session.Get("key-1");
   long key1Value = BitConverter.ToInt64(key1, 0);
 
   int? key2Value = this.HttpContext.Session.GetInt32("key-2");
   string key3Value = this.HttpContext.Session.GetString("key-3");
 
   return Content("OK!");
}
همانطور که ملاحظه می‌کنید، سه متد Set، SetInt32 و SetString در اینجا برای تنظیم key/valueهای سشن، از پیش موجود هستند.
حالت Set آن آرایه‌ای از بایت‌ها را دریافت می‌کند و می‌توان برای حالت serialization اشیاء، مفید باشد.
دقیقا معادل همین سه متد، متدهای Get، GetInt32 و GetString برای بازیابی مقادیر سشن طراحی شده‌اند و باید دقت داشت که خروجی‌های این‌ها می‌توانند نال نیز باشند. به همین جهت خروجی GetInt32 آن نال پذیر است.


توسعه‌ی متدهای پیش فرض کار با سشن‌ها

سه متد یاد شده‌ی کار با سشن‌ها در ASP.NET Core هرچند ضروری هستند، اما کافی نیستند. برای توسعه‌ی آن‌ها می‌توان متدهای الحاقی را تدارک دید که نمونه‌ای از آن‌ها را ذیل مشاهده می‌کنید:
using System;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
 
namespace Core1RtmEmptyTest.StartupCustomizations
{
    public static class SessionExts
    {
        public static void SetDateTime(this ISession collection, string key, DateTime value)
        {
            collection.Set(key, BitConverter.GetBytes(value.Ticks));
        }
 
        public static DateTime? GetDateTime(this ISession collection, string key)
        {
            var data = collection.Get(key);
            if (data == null)
            {
                return null;
            }
            var dateInt = BitConverter.ToInt64(data, 0);
            return new DateTime(dateInt);
        }
 
        public static void SetObject(this ISession session, string key, object value)
        {
            var stringValue = JsonConvert.SerializeObject(value);
            session.SetString(key, stringValue);
        }
 
        public static T GetObject<T>(this ISession session, string key)
        {
            var stringValue = session.GetString(key);
            return JsonConvert.DeserializeObject<T>(stringValue);
        }
    }
}
در اینجا با استفاده از کلاس BitConverter و امکان سریالایز مقادیر توسط آن به آرایه‌ای از بایت‌ها، امکان کار با متد‌های عمومی Set و Get را یافته‌ایم.
و یا جهت کار با اشیاء پیچیده‌تر می‌توان از کتابخانه‌ی JSON.NET استفاده کرد. به عبارتی در این نگارش از ASP.NET، کار سریالایز و دی‌سریالایز اشیاء، به برنامه نویس واگذار شده‌است و اینکه در پشت صحنه از چه کتابخانه‌ای می‌خواهید استفاده کنید، در اختیار خودتان است.
البته باید دقت داشت که در اینجا وابستگی JSON.NET به صورت خودکار در دسترس است. از این جهت که بسیاری از وابستگی‌های ASP.NET Core مانند مورد ذیل، به JSON.NET وابسته‌اند و نصب آن‌ها به معنای نصب خودکار JSON.NET نیز هست:
{
    "dependencies": {
     //same as before
     "Microsoft.Extensions.Configuration.Json": "1.0.0"
   }
}
اگر لیست بسته‌های وابسته‌ی به JSON.NET را می‌خواهید مشاهده کنید، فایل project.lock.json را گشوده و در آن Newtonsoft.Json را جستجو کنید.


یک مطلب تکمیلی

در اینجا نیز امکان ذخیره سازی سشن‌ها در بانک اطلاعاتی بجای حافظه‌ی فرار سرور درنظر گرفته شده‌است و برای این حالت، بانک‌های اطلاعاتی NoSQL ویژه‌ای به نام key/value stores مانند بانک اطلاعاتی فوق سریع Redis پیشنهاد می‌شود؛ هرچند امکان کار با SQL Server نیز در اینجا وجود دارد، اما برای کش سرورهای مبتنی بر key/value ها، بانک اطلاعاتی Redis، انتخاب اول است.
Managing Application State
نظرات اشتراک‌ها
Chrome و قابلیت DirectWrite
متاسفانه مشکل نمایش صحیح وب فونت‌ها در مرورگر کروم، با راه حل‌های متنوع ارائه شده (با یک جستجوی کوچک، انواع و اقسام راه حل‌ها را مشاهده می‌کنید) هنوز پا برجاست؛ مهمتر اینکه این مشکل همیشگی نیست:
  • گاهی کروم فونت‌ها را صحیح نمایش می‌دهد و گاهی خیر؛
  • در قسمتی از صفحه فونت‌ها درست نمایش داده می‌شوند و در قسمت دیگر خیر؛
  • با رفرش کردن صفحه سالم، فونت‌ها دچار مشکل می‌شوند و گاهی بالعکس؛
  • بعضی اوقات کاراکترهای مربعی نمایش داده می‌شوند و گاهی کاراکترهای نامفهوم و به هم ریخته.
برای نمونه در همین سایت:
 


به هر حال امیدوارم راه حل مناسبی برای این مشکل (با در نظر گرفتن اینکه از فونت استاندارد استفاده شود)  پیدا شود...!

نظرات مطالب
تنظیمات CORS در ASP.NET Core
کروم از نسخه 108 امکان استفاده از این پرچم را نمی‌دهد.
گزینه دیگر برای معرفی امن آدرس‌ها و اجازه دسترسی به private-network از طرف آدرس‌ها استفاده از گزینه Insecure origins treated as secure  از طریق پرچم زیر است:
chrome://flags/#unsafely-treat-insecure-origin-as-secure 
برای معرفی آدرس‌ها، آن‌ها را به صورت comma-separated وارد می‌کنیم و وضعیت گزینه را از Disabled به Enabled تغییر می‌دهیم. با راه‌اندازی مجدد کروم، تنظیمات ذخیره خواهد شد.

مطالب
حل مشکل ویژوال استودیو در سیستمهایی که از رزولوشن (DPI) بالا و مانیتور های 4K استفاده می کنند
مدتی بود بر روی یک پروژه‌ی اتوماسیون اداری در VB.NET کار می‌کردیم. پروژه‌ی ما بر روی سیستمی با رزولوشن بالا  2160 * 3840 و مانیتور 4K قرار داشت. بعد از اینکه لایه بندی و کد‌های نرم افزار نوشته شد، نوبت به طراحی اینترفیس پروژه رسید. با مشکلی عجیب روبرو شدیم، به این صورت که در قسمت طراحی ویژوال استودیو، منوها، دکمه‌ها و ... بیش از حد معمول کوچک و به هم ریخته بود. ولی زمانیکه پروژه اجرا می‌شد، نسبت به طراحی که در سمت وِیژوال استودیو انجام داده بودیم، دکمه‌ها  بزرگتر و منوها بزرگتر و شکسته شده بودند. در حقیقت، سمت طراحی و سمت اجرای پروژه، هم خوانی نداشتند. در حالیکه ما قبلا بر روی مانیتور‌های HD و رزولوشن‌ها HD، هیچ مشکلی در طراحی و اجرای پروژه نداشتیم و هم خوانی لازم را باهم داشتند. بعد از جستجوهای متعدد، به این مطلب پی بردیم که این مشکل بیشتر برنامه نویسانی هست که از سیستم‌هایی با رزولوشن بالا و مانیتور‌های 4K استفاده می‌کنند و پاسخ مناسبی به کاربران داده نشده است. با تست راه‌های متعدد و جستجوهای پی در پی، به پاسخ قطعی رسیدیم و خواستم این مطلب  را به صورت مقاله‌ای کوتاه، با شما به اشتراک بگذارم.
مشخصات سیستمی که مشکل زیر را دارد : ویندوز 10  نسخه  Enterprise  x64 و ویژوال استودیو 2015 نسخه  Enterprise 
نمونه اسکرین شات گرفته شده که مشکل یکی از کاربران ایرانی بود و برای حل مشکل خود، اسکرین شات صفحه نمایش خود را قرار داده بود و به پاسخ قطعی نرسیده بود:

  اگر ملاحظه کنید، تصویر سمت راست، از پروژه‌ای بر روی VirtualBox با رزولوشن و DPI پایین در دیزاین ویژوال استودیو و تصویر سمت چپ از همان پروژه در دیزاین ویژوال استودیو با رزولوشن بالا و مانیتور 4K تهیه شده‌است و ملاحظه می‌کنید که پروژه به هم ریخته است و این مشکل در خیلی از برنامه‌های دیگر نیز موجود می‌باشد؛ مانند SQL SERVER و ...
 نمونه اسکرین شات گرفته شده از بعضی پنجره‌های SQL server 

حال برای رفع این مشکل چه باید کرد؟ به صورت زیر عمل می‌کنیم  

  1. به مسیر زیر در رجیستری مراجعه می‌کنیم :    
HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows > CurrentVersion > SideBySide
 و رایت کلیک کرده  NEW > DWORD (32 bit) Value  انتخاب کرده و نام را PreferExternalManifest وارد کرده و Value را بر روی 1 قرار می‌دهیم .

     

2. نرم افزار Resourcehacke را دانلود کرده و آن‌را اجرا کرده و از قسمت File، بر روی Open کلیک کرده و مسیر ویژوال استودیو را به نرم افزار داده و  Ok را انتخاب می‌کنیم . 
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE


بعد از بارگذاری اطلاعات ویژوال استودیو در نرم افزار  Resourcehacke، از سمت چپ بر روی Manifest و 1:1033 کلیک کرده و dpiAware را بر روی False قرار می‌دهیم .
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <application xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <windowsSettings> 
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">False</dpiAware> 
    </windowsSettings> 
  </application> 
</assembly>

ودر آخر سیستم را ریستارت کرده و با همان رزولوشن بالا و مانیتور 4K، ویژوال استودیو را اجرا می‌کنیم و ملاحظه میکنیم که مشکل خاصی وجود ندارد و سمت دیزاین با سمت اجرای پروژه همخوانی دارد و همسان می‌باشد.

نظرات مطالب
اجرای وظایف زمان بندی شده با Quartz.NET - قسمت دوم
بله. زمانیکه تمام سایت‌ها با یک Application pool مدیریت می‌شوند، تمام آن‌ها توسط یک وهله از w3wp.exe اجرا خواهند شد. با تعریف Application poolهای مجزا، هر سایت، یک وهله‌ی مجزا از w3wp.exe را به خود اختصاص خواهد داد. یعنی اگر Task manager سرور را بررسی کنید، به ازای هر سایت، یک w3wp.exe با pid مجزا قابل مشاهده است. به این ترتیب اگر pid=1234 کرش کرد، تاثیری روی pid=4321 نخواهد داشت.
مطالب
Gulp #4
همانطورکه در مقاله‌ی قبلی پایه‌ی ورک فلوی خود را راه اندازی کردیم، در این مقاله می‌خواهیم با طراحی یک صفحه، با بوت استرپ شخصی سازی شده، در عمل با کارایی گالپ آشنا شویم.
دمو پایانی:


به هنگام سازی مرورگر و بارگذاری مجدد به صورت خودکار

یکی از موارد فوق العاده تکراری در هنگام توسعه‌ی وب، برای یک توسعه دهنده سمت کاربر (Front end Developer)  ریلود کردن مرورگر است. همچنین تست وب سایت یا آپلود در موبایل و سایر داستگاه‌ها، متداول است. با پلاگین گالپ می‌توان این مشکل را به صورت بهینه‌ای حل کرد.

نصب

برای نصب دستور زیر را در مسیر پروژه، در ترمینال سیستم عامل خود وارد کنید.
npm install browser-sync gulp --save-dev
می‌دانیم برای استفاده از یک پلاگین باید توسط متد require آن را به یک متغیر انتساب دهیم؛ به صورت زیر:
var gulp = require('gulp'),
    sass = require('gulp-ruby-sass'),
    notify = require('gulp-notify'),
    browserSync = require('browser-sync'), // Add browser syns plugin
    bower = require('gulp-bower');
توجه کنید هر پلاگینی که اضافه می‌کنید، باید تسک مربوط به آن را بنویسیم تا بتوانیم از آن استفاده کنیم. برای این پلاگین فقط مشخص کردن مسیر root سرور کافی است.
gulp.task('browserSync', function() {
    browserSync({
        server: {
            baseDir: './' //our server root
        }
    });
});
حال می‌خواهیم با زدن gulp watch، تمام کارهای ما به صورت خودکار انجام شوند. اما این دستور که در جلسه‌ی قبل آن‌را تعریف کردیم، فقط منتظر انجام یک تغییر است. تسک watch را به گونه‌ای تغییر می‌دهیم که ابتدا تسک‌های css , brower sync انجام شوند (به دلیل اینکه باید ابتدا، سرور راه اندازی شود) سپس گالپ منتظر تغییرات باشد و آنها را اعمال کند. 
gulp.task('watch', [ 'css','browserSync'], function() {

})
تسک‌های html,css,browserSync قبل از تسک watch اجرا می‌شوند. طبق مستندات، این پلاگین یکی از توابع API متد watch است و کار آن همانند متد مشابهی در گالپ است. آن را برای ریلود خودکار مرورگر استفاده می‌کنیم.
// Rerun the task when a file changes
gulp.task('watch', ['html', 'css','browserSync'], function() {
    gulp.watch(config.sassPath + '/**/*.scss', ['css']);
    gulp.watch(config.htmlPath , ['html'] )
    browserSync.watch("./*.html").on("change", browserSync.reload); // browserSync watch task
});
می‌خواهیم بعد از کامپایل، فایل‌های sass هم مرورگر دوباره بارگذاری شوند. کد زیر را به انتهای تسک css اضافه می‌کنیم:
.pipe(browserSync.reload({
      stream: true
  }));
بسیار خوب با انجام این کار‌ها پلاگین باید به‌درستی کار کند.

شخصی سازی بوت استرپ

برای شخصی سازی بوت استرپ کافی است ابتدا فایل‌های sass بوت استرپ و FontAwesome را در style.scss ایمپورت کنیم؛ به این صورت:
@import "bootstrap";
@import "font-awesome";
حال دستور gulp را می‌زنیم. با اینکار فایل style.scss کامپایل می‌شود. می‌خواهیم یک فونت فارسی و یک قالب فلت را به پروژه‌ا‌مان اعمال کنیم. من فایل‌ها را اضافه کرده‌ام و شما با یک نگاه می‌توانید، چیزی را که گفتم درک کنید.
@import "fonts-fa";
@import "variable";
@import "bootstrap";
@import "font-awesome";
@import "rtl.scss";
@import "typography";
نکته : سعی کنید برای استایل هر قسمت، یک فایل مجزا درست کنید؛ مانند مثال بالا که در پروژه لحاظ شده.
برای توسعه‌ی پروژه، ابتدا مخزن گیت هاب را فورک کرده و با زدن دستورات زیر کار خود را آغاز کنید:
  1. sudo npm install
  2. gulp
  3. gulp watch


مخزن گیت هاب : کامیت : 

Add : browserSync plugin and index.html 
نظرات مطالب
آموزش MDX Query - قسمت ششم – شروع کار با دستورات MDX
با سلام خدمت شما، بسیار سپاسگذارم به خاطر این سری مقالات آموزشی که باعث شد با زبان جذاب و فوق العاده‌ی MDX آشنا شوم.
بنده با گزارشات آماری cross tab آشنا هستم، خروجی مثال هایتان دقیقا مشابه با خروجی گزارشات cross tab است (مو نمی‌زنه!)
نوشتن Query‌های pivoting/cross tabulation با این زبان نسبت به زبان SQL واقعا ساده‌تر است. حقیقتا لذت بردم.
فقط خواهشی داشتم، اگر مقدور است به مثال هایی بپردازید که در آنها ستون‌ها یا سطرها در Range‌های مختلف گروه بندی شوند.
مثال:

جدول فوق یک گزارش آماری cross tab است. که مشخص کرده افراد (مرد و زن) در رده‌های سنی مختلف (زیر 10 سال، بین 10 و 20 سال و ...) روزانه چند دقیقه تلوزیون تماشا می‌کنند (کمتر از 20 دقیقه، بین 20 تا 40 دقیقه..). این بازه‌ها را میشه برای داده هایی مثل تاریخ، روزها، هفته ها، ماه‌ها و ... نیز در نظر گرفت.
و سوالی نیز داشتم، آیا می‌توان Query‌های MDX را به T-SQL تبدیل کرد (منظور بصورت خودکار است نه بازنویسی آن) ؟
و درخواست پایانی، لطفا به بحث Reporting هم بپردازید که ببینیم این نتیجه در قالب گزارش تجاری چگونه ظاهر می‌شوند.
مطالب
آشنایی با CLR: قسمت نهم
net framework. شامل Framework Class Library یا به اختصار FCL است. FCL مجموعه‌ای از dll اسمبلی‌هایی است که صدها و هزاران نوع در آن تعریف شده‌اند و هر نوع تعدادی کار انجام می‌دهد. همچنین مایکروسافت کتابخانه‌های اضافه‌تری را چون azure و Directx نیز ارائه کرده است که باز هر کدام شامل نوع‌های زیادی می‌شوند. این کتابخانه به طور شگفت آوری باعث سرعت و راحتی توسعه دهندگان در زمینه فناوری‌های مایکروسافت گشته است.

تعدادی از فناوری‌هایی که توسط این کتابخانه پشتیبانی می‌شوند در زیر آمده است:

Web Service: این فناوری اجازه‌ی ارسال و دریافت پیام‌های تحت شبکه را به خصوص بر روی اینترنت، فراهم می‌کند و باعث ارتباط جامع‌تر بین برنامه‌ها و فناوری‌های مختلف می‌گردد. در انواع جدیدتر WCF و Web Api نیز به بازار ارائه شده‌اند.

webform و MVC : فناوری‌های تحت وب که باعث سهولت در ساخت وب سایت‌ها می‌شوند که وب فرم رفته رفته به سمت منسوخ شدن پیش می‌رود و در صورتی که قصد دارید طراحی وب را آغاز کنید توصیه میکنم از همان اول به سمت MVC بروید.

Rich Windows GUI Application : برای سهولت در ایجاد برنامه‌های تحت وب حالا چه با فناوری WPF یا فناوری قدیمی و البته منسوخ شده Windows Form.
Windows Console Application: برای ایجاد برنامه‌های ساده و بدون رابط گرافیکی.
Windows Services: شما می‌توانید یک یا چند سرویس تحت ویندوز را که توسط Service Control Manager یا به اختصار SCM کنترل می‌شوند، تولید کنید.
Database stored Procedure: نوشتن stored procedure بر روی دیتابیس‌هایی چون sql server و اوراکل و ... توسط فریم ورک دات نت مهیاست.
Component Libraray: ساخت اسمبلی‌های واحدی که می‌توانند با انواع مختلفی از موارد بالا ارتباط برقرار کنند.
Portable Class Libary : این نوع پروژه‌ها شما را قادر می‌سازد تا کلاس‌هایی با قابلیت انتقال پذیری برای استفاده در سیلور لایت، ویندوز فون و ایکس باکس و فروشگاه ویندوز و ... تولید کنید.

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

در CLR مفهومی به نام Common Type System یا CTS وجود دارد که توضیح می‌دهد نوع‌ها باید چگونه تعریف شوند و چگونه باید رفتار کنند که این قوانین از آنجایی که در ریشه‌ی CLR نهفته است، بین تمامی زبان‌های دات نت مشترک می‌باشد. تعدادی از مشخصات این CTS در زیر آورده شده است ولی در آینده بررسی بیشتری روی آنان خواهیم داشت:

  • فیلد
  • متد
  • پراپرتی
  • رویدادها

CTS همچنین شامل قوانین زیادی در مورد وضعیت کپسوله سازی برای اعضای یک نوع دارد:

  • private
  • public
  • Family یا در زبان‌هایی مثل سی ++ و سی شارپ با نام protected شناخته می‌شود.
  • family and assembly: این هم مثل بالایی است ولی کلاس مشتق شده باید در همان اسمبلی باشد. در زبا‌ن‌هایی چون سی شارپ و ویژوال بیسیک، چنین امکانی پیاده سازی نشده‌است و دسترسی به آن ممکن نیست ولی در IL Assembly چنین قابلیتی وجود دارد.
  • Assembly یا در بعضی زبان‌ها به نام internal شناخته می‌شود.
  • Family Or Assembly: که در سی شارپ با نوع Protected internal شناخته می‌شود. در این وضعیت هر عضوی در هر اسمبلی قابل ارث بری است و یک عضو فقط می‌تواند در همان اسمبلی مورد استفاده قرار بگیرد.

موارد دیگری که تحت قوانین CTS هستند مفاهیم ارث بری، متدهای مجازی، عمر اشیاء و .. است.

یکی دیگر از ویژگی‌های CTS این است که همه‌ی نوع‌ها از نوع شیء Object که در فضای نام system قرار دارد ارث بری کرده‌اند. به همین دلیل همه‌ی نوع‌ها حداقل قابلیت‌هایی را که یک نوع object ارئه میدهد، دارند که به شرح زیر هستند:

  • مقایسه‌ی دو شیء از لحاظ برابری.
  • به دست آوردن هش کد برای هر نمونه از یک شیء
  • ارائه‌ای از وضعیت شیء به صورت رشته ای
  • دریافت نوع شیء جاری
CLS
وجود COM‌ها به دلیل ایجاد اشیاء در یک زبان متفاوت بود تا با زبان دیگر ارتباط برقرار کنند. در طرف دیگر CLR هم بین زبان‌های برنامه نویسی یکپارچگی ایجاد کرده است. یکپارچگی زبان‌های برنامه نویسی علل زیادی دارند. اول اینکه رسیدن به هدف یا یک الگوریتم خاص در زبان دیگر راحت‌تر از زبان پایه پروژه است. دوم در یک کار تیمی که افراد مختلف با دانش متفاوتی حضور دارند و ممکن است زیان هر یک متفاوت باشند.
برای ایجاد این یکپارچگی، مایکروسافت سیستم CLS یا Common Language Specification را راه اندازی کرد. این سیستم برای تولیدکنندگان کامپایلرها جزئیاتی را تعریف می‌کند که کامپایلر آن‌ها را باید با حداقل ویژگی‌های تعریف شده‌ی CLR، پشتیبانی کند.


CLR/CTS مجموعه‌ای از ویژگی‌ها را شامل می‌شود و گفتیم که هر زبانی بسیاری از این ویژگی‌ها را پشتیبانی می‌کند ولی نه کامل. به عنوان مثال برنامه نویسی که قصد کرده از IL Assembly استفاده کند، قادر است از تمامی این ویژگی‌هایی که CLR/CTS ارائه می‌دهند، استفاده کند ولی تعدادی دیگر از زبان‌ها مثل سی شارپ و فورترن و ویژوال بیسیک تنها بخشی از آن را استفاده می‌کنند و CLS حداقل ویژگی که بین همه این زبان‌ها مشترک است را ارائه می‌کند.
شکل زیر را نگاه کنید:

یعنی اگر شما دارید نوع جدیدی را در یک زبان ایجاد می‌کنید که قصد دارید در یک زبان دیگر استفاده شود، نباید از امتیازات ویژه‌ای که آن زبان در اختیار شما می‌گذارد و به بیان بهتر CLS آن‌ها را پشتیبانی نمی‌کند، استفاده کنید؛ چرا که کد شما ممکن است در زبان دیگر مورد استفاده قرار نگیرد.

به کد زیر دقت کنید. تعدادی از کدها سازگاری کامل با CLS دارند که به آن‌ها CLS Compliant گویند و تعدادی از آن‌ها non-CLS-Compliant هستند یعنی با CLS سازگاری ندارند ولی استفاده از خاصیت [(assembly: CLSCompliant(true]  باعث می‌شود که تا کامپایلر از پشتیبانی و سازگاری این کدها اطمینان کسب کند و در صورت وجود، از اجرای آن جلوگیری کند. با کمپایل کد زیر دو اخطار به ما میرسد.
using System;

// Tell compiler to check for CLS compliance
[assembly: CLSCompliant(true)]

namespace SomeLibrary {

// Warnings appear because the class is public
public sealed class SomeLibraryType {

// Warning: Return type of 'SomeLibrary.SomeLibraryType.Abc()'
// is not CLS­compliant
public UInt32 Abc() { return 0; }

// Warning: Identifier 'SomeLibrary.SomeLibraryType.abc()'
// differing only in case is not CLS­compliant
public void abc() { }

// No warning: this method is private
private UInt32 ABC() { return 0; }
}
}

اولین اخطار اینکه یکی از متدها یک عدد صحیح بدون علامت unsigned integer را بر می‌گرداند که همه‌ی زبان‌ها آن را پشتیبانی نمی‌کنند و خاص بعضی از زبان هاست.
دومین اخطار اینکه دو متد یکسان وجود دارند که در حروف بزرگ و کوچک تفاوت دارند. ولی زبان هایی چون ویژوال بیسیک نمی‌توانند تفاوتی بین دو متد abc و ABC بیابند.

نکته‌ی جالب اینکه اگر شما کلمه public را از جلوی نام کلاس بردارید تمامی این اخطارها لغو می‌شود. به این خاطر که این‌ها اشیای داخلی آن اسمبلی شناخته شده و قرار نیست از بیرون به آن دسترسی صورت بگیرد. عضو خصوصی کد بالا را ببینید؛ کامنت بالای آن می‌گوید که چون خصوصی است هشداری نمی‌گیرد، چون قرار نیست در زبان مقصد از آن به طور مستقیم استفاده کند.
برای دیدن قوانین CLS به این صفحه مراجعه فرمایید.

سازگاری با کدهای مدیریت نشده
در بالا در مورد یکپارچگی و سازگاری کدهای مدیریت شده توسط CLS صحبت کردیم ولی در مورد ارتباط با کدهای مدیریت نشده چطور؟
مایکروسافت موقعیکه CLR را ارئه کرد، متوجه این قضیه بود که بسیاری از شرکت‌ها توانایی اینکه کدهای خودشون را مجددا طراحی و پیاده سازی کنند، ندارند و خوب، سورس‌های مدیریت نشده‌ی زیادی هم موجود هست که توسعه دهندگان علاقه زیادی به استفاده از آن‌ها دارند. در نتیجه مایکروسافت طرحی را ریخت که CLR هر دو قسمت کدهای مدیریت شده و نشده را پشتیبانی کند. دو نمونه از این پشتیبانی را در زیر بیان می‌کنیم:
یک. کدهای مدیریت شده می‌توانند توابع مدیریت شده را در قالب یک dll صدا زده و از آن‌ها استفاده کنند.
دو. کدهای مدیریت شده می‌توانند از کامپوننت‌های COM استفاده کنند: بسیاری از شرکت‌ها از قبل بسیاری از کامپوننت‌های COM را ایجاد کرده بودند که کدهای مدیریت شده با راحتی با آن‌ها ارتباط برقرار می‌کنند. ولی اگر دوست دارید روی آن‌ها کنترل بیشتری داشته باشید و آن کدها را به معادل CLR تبدیل کنید؛ میتوانید از ابزار کمکی که مایکروسافت همراه فریم ورک دات نت ارائه کرده است استفاده کنید. نام این ابزار TLBIMP.exe می‌باشد که از Type Library Importer گرفته شده است.

سه. اگر کدهای مدیریت نشده‌ی زیادتری دارید شاید راحت‌تر باشد که برعکس کار کنید و کدهای مدیریت شده را در در یک برنامه‌ی مدیریت نشده اجرا کنید. این کدها می‌توانند برای مثال به یک Activex یا shell Extension تبدیل شده و مورد استفاده قرار گیرند. ابزارهای TLBEXP .exe و RegAsm .exe برای این منظور به همراه فریم ورک دات نت عرضه شده اند.
سورس کد Type Library Importer را میتوانید در کدپلکس بیابید.
در ویندوز 8 به بعد مایکروسافت API جدید را تحت عنوان WinsowsRuntime یا winRT ارائه کرده است . این api یک سیستم داخلی را  از طریق کامپوننت‌های com ایجاد کرده و به جای استفاده از فایل‌های کتابخانه‌ای، کامپوننت‌ها api هایشان را از طریق متادیتاهایی بر اساس استاندارد ECMA که توسط تیم دات نت طراحی شده است معرفی می‌کنند.
زیبایی این روش اینست که کد نوشته شده در زبان‌های دات نت  می‌تواند به طور مداوم با api‌های winrt ارتباط برقرار کند. یعنی همه‌ی کارها توسط CLR انجام می‌گیرد بدون اینکه لازم باشد از ابزار اضافی استفاده کنید. در آینده در مورد winRT بیشتر صحبت می‌کنیم.
 
سخن پایانی: ممنون از دوستان عزیز بابت پیگیری مطالب تا بدینجا. تا این قسمت فصل اول کتاب با عنوان اصول اولیه CLR بخش اول مدل اجرای CLR به پایان رسید.
ادامه‌ی مطالب بعد از تکمیل هر بخش در دسترس دوستان قرار خواهد گرفت.
نظرات مطالب
توزیع پروژه‌های ASP.NET Core 1.1 بدون ارائه فایل‌های View آن
ارتقاء به ASP.NET Core 2.1: امکان کامپایل فایل‌های Razor در پروژه‌های Class library (یا پشتیبانی از طراحی افزونه‌پذیر به صورت توکار)


در نگارش 2.1 می‌توان فایل‌های razor (هم صفحات Razor و هم Viewهای Razor) را به همراه کنترلرها و مدل‌های آن‌ها داخل class libraries مجزا قرار داد و استفاده کرد. استفاده کننده فقط کافی است ارجاعی را به این کتابخانه‌ها اضافه کند تا امکانات آن‌ها قابل استفاده شوند.
فعالسازی این قابلیت در یک class library نیاز به تغییرات ذیل را در یک فایل csproj دارد (مشخص کردن sdk، تعیین کامپایل شدن viewها و صفحاتی که باید الحاق شوند):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <ResolvedRazorCompileToolset>RazorSdk</ResolvedRazorCompileToolset>
    <RazorCompileOnBuild>true</RazorCompileOnBuild>
    <IncludeContentInPack>false</IncludeContentInPack>
  </PropertyGroup>
<ItemGroup>
    <Content Include="Pages\**\*.cshtml" />
  </ItemGroup>
<ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.1.0-preview1-final" />
  </ItemGroup>
</Project>

یک نکته‌ی تکمیلی
اگر برنامه‌های هاست کننده‌ی این پلاگین‌ها، دقیقا در مسیرهای متناظری صفحات و یا Viewهای Razor را قرار دهد، می‌تواند این صفحات را بازنویسی کند.