نظرات مطالب
ایجاد alert,confirm,prompt هایی متفاوت با jQuery Impromptu
ممنون،
یه سوال بنده یه فرم ثبت نام دارم که با کلیک بر روی Botton اطلاعات در دیتابیس درج می‌شود حالا می‌خوام بعد از ثبت اطلاعات یه alert به کاربر نشون بده که اطلاعات با موفقیت ثبت شد ولی مشکل اینجاست که وقتی کاربر روی Button کلیک میکنه چون صفحه PostBack میشه دیگه پیغام به کاربر نمایش داده نمیشه،اگه امکان داره بنده رو راهنمایی بفرمائید.
دقیقا مثل همین قسمت ارسال نظر سایت.
مطالب
استفاده از چند فرم در کنار هم در ASP.NET MVC

اجرای این نوع صفحات کار سختی نیست؛ با کمی جستجو در اینترنت مثلا در اینجا میتوانید چیزهای خوبی پیدا کنید. اما متاسفانه اکثر مثال‌ها چیزی شبیه قرار دادن پارشال "ورود اعضا" در کنار پارشال "ثبت نام" هستند. حتما متوجه شده‌اید که معمولا این دو صفحه پس از  PostBack به صفحه‌ای جدید هدایت میشوند و یا در بهترین حالت به کمک Ajax ، پس از انجام عملیات، پیامی به کاربر نمایش میدهیم.

در این مقاله سعی شده روشی برای ایجاد چند فرم در یک View توضیح داده شود با این شرط که: 

اولا : از Ajax یا هلپر ایجکسی استفاده نکنیم.

ثانیا : پس از post-back، عملیات Redirect را انجام ندهیم و صفحه جاری را حفظ کنیم؛ چه قرار باشد همه چیز درست انجام شده باشد و چه مشکلی پیش آمده باشد و پیام خطایی در کنار فیلد‌ها نمایش داده شود. 

 در این روش به این نکته توجه شده که هر مدل پس از Post-back حفظ شود و مستقل از دیگری رفتار کند. مثلا اگر یکی از فرم‌ها ناقص پر شد و دکمه‌ی ارسال آن فشرده شد، پس از Post-back، فقط و فقط اجزای همین فرم Validate شود و فرم دوم بدون تغییر باقی بماند. 

ویوی زیر را در نظر بگیرید. در layout، دو پارشال، به کمک اکشن‌متد فراخوانی شده‌اند:

ViewModelهای مرتبط با این دو بخش به شکل زیر هستند : 

ContactVM .cs  

public class ContactVM
    {
        [Display(Name = "نام")]
        [Required(ErrorMessage = "لطفا {0} را وارد کنید")]
        public string Name { get; set; }

              [EmailAddress(ErrorMessage = "آدرس ایمیل صحیح نیست")]
        [DataType(DataType.EmailAddress)]
        [Display(Name = "آدرس ایمیل")]
        [Required(ErrorMessage = "لطفا {0} را وارد کنید")]
        public string EmailAddress { get; set; }

        [Display(Name = "متن پیام")]
        [Required(ErrorMessage = "حرفی برای گفتن ندارید؟")]
        public string Description { get; set; }

        [Required(ErrorMessage = "لطفا {0} را وارد کنید")]
        [Display(Name = "حاصل جمع")]
        public string Captcha { get; set; }
    }

SubscriberVM .cs

    public class SubscriberVM
    {   
        /*[RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "آدرس ایمیل صحیح نیست")]*/
          [EmailAddress(ErrorMessage = "آدرس ایمیل صحیح نیست")] /*.Net4.5*/
        [Display(Name = "ایمیل")]
        [Required(ErrorMessage = "لطفا {0} را وارد کنید")]
        public string Email { get; set; }

        [Display(Name = "وضعیت")]
        public bool IsActive { get; set; }    
    }

در Layout، دو اکشن متد صدا زده شده‌اند که وظیفه ارسال ویوهای هر کدام به Layout را به عهده دارند :

        <div class="row footerclass">
            <div class="col-md--6">
                @Html.Action("Subscribers", "Home")
            </div>
            <div class="col-md-6">
                @Html.Action("Contact", "Home")
            </div>

        </div>

اکشن متدهای این دو پارشال به شکل زیر هستند :

public ActionResult Contact()
        {
            return PartialView("_Contact", model);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]

        public ActionResult Contact(ContactVM model)
        {
              if (ModelState.IsValid)
                {
//Do Something                    
                }
            return PartialView("_Contact", model);
        }

        public ActionResult Subscribers()
        {
            return PartialView("_Subscribers");
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Subscribers(SubscriberVM model)
        {
                if (ModelState.IsValid)
                {
//Do Something
                }
            }
            return PartialView("_Subscribers",model);
        }

و اما ویوهایی که قرار است نمایش داده شوند:

Contact.Cshtml

@model IrsaShop.Models.ViewModel.ContactVM


<span></span><span>تماس با ما</span>
<hr />

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <div>
        @Html.TextBoxFor(m => m.Name, new { @class = "form-control", @id = "name", @name = "name", placeholder = "نام" })
        @Html.ValidationMessageFor(m => m.Name)
    </div>
    <div>
        @Html.TextBoxFor(m => m.EmailAddress, new { @class = "form-control", @id = "email", @name = "email", placeholder = "ایمیل", @style = "direction: ltr" })
        @Html.ValidationMessageFor(m => m.EmailAddress)
    </div>
    <div>
        @Html.TextAreaFor(model => model.Description, new { @class = "form-control", @id = "message", @name = "message", placeholder = "پیام", @style = "max-width: 100%;height: 90px;" })
    </div>
    <div>
        <input type="button" value="" id="refresh" />
        <img alt="Captcha" id="imgcpatcha" src="@Url.Action("CaptchaImage","Captcha")" />
    </div>
    <div>
        @Html.TextBoxFor(model => model.Captcha, new { @class = "form-control", placeholder = "حاصل جمع؟" })
        @Html.ValidationMessageFor(model => model.Captcha)

    </div>
    <div>
        <input type="submit" value="ارسال" name="submitValue" />
    </div>
}

_Subscriber.Csh tml 

@model IrsaShop.Models.SubscriberVM

<span></span><span>خبرنامه</span>
<hr/>

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <div>

        <div>
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control right-buffer top-buffer pull-right", @id = "email", @name = "email", placeholder = "ایمیل", @style = "direction: ltr;width: 50%", @required = "required" })
       @*     <button type="submit" name="submitValue">ثبت ایمیل</button>*@
            <input type="submit" value="ثبت ایمیل" name="submitValue" />
        </div>
        
    </div>
   @Html.ValidationMessageFor(m => m.Email,"",new { @class = "right-buffer pull-right"})
   
}

نکته اول : هیچ نوع ورودی برای Html.BeginForm در نظر گرفته نشده است. اگر اکشن متدی را برای صدا زدن در این بخش در نظر بگیرید، هنگام Postback به مشکل برخورد خواهید کرد؛ چون آدرس آن اکشن متد به شکل صریح در آدرس مرورگر فراخوانی میشود و پارشال ما پس از Post-back به تنهایی و بدون Layout نمایش داده خواهد شد. اسم بردن از اکشن متد وقتی کارساز است که آن اکشن متد قرار باشد یک Redirect انجام دهد ولی هدف ما این است که صفحه را از دست ندهیم و پیام‌های خطای ModelState را در همان صفحه قبل و پس از Post-back ببینیم و همچنین پس از انجام عملیات (مثلا ارسال پیام) همین صفحه نمایش داده شود. 

نکته دوم : نکته اول یک مشکل دارد! اگر به شکل صریح اکشن متد مربوط به Post-back مشخص نشود، بطور اتوماتیک تمامی اکشن متدهایی که ویژگی [HttpPost] دارند اجرا خواهند شد. این یعنی هر دو اکشن متد Contact و Subscriber اجرا می‌شوند و بنابر آنچه در اکشن متدها نوشته‌ایم هر دو ModelState بررسی می‌شود که این هدف ما نیست. مثلا فرم سمت چپ را تکمیل کرده ایم و دکمه "ثبت ایمیل" را فشار داده‌ایم و صفحه Postback می‌شود و با اینکه ایمیل در بانک ثبت شده اما فرم سمت راستی با خطا ظاهر میشود که چرا فیلدها خالی هستند!؟ 

برای حل این مشکل کافیست خاصیت name مربوط به دکمه‌ها را به شکل یک ورودی برای اکشن متدها بفرستیم و بر اساس وضعیت آن تنها state مدل مورد نظر خودمان را بررسی کنیم. پس اصلاح زیر را برای اکشن متدهای دارای ویژگی [HttpPost] انجام میدهیم.

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]

        public ActionResult Contact(ContactVM model, , string submitValue)
        {
   if (submitValue == "ارسال") 
                {
                 if (ModelState.IsValid)
                {
//Do Something                    
                }
}   else
                {
                         ModelState.Clear();
                }        
            return PartialView("_Subscribers", model);
        }

        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
public ActionResult Subscribers(SubscriberVM model, string submitValue)
        {
             if (submitValue == "ثبت ایمیل") 
            {
if (ModelState.IsValid)
                {
//Do Something
                }
}
            else
            {
                ModelState.Clear();
            }
            return PartialView("_Subscribers");
        }

نکته سوم : در این روش سعی کنید از ViewModel  استفاده کنید و سعی کنید ویو مدل‌ها پراپرتی‌های با نام یکسان نداشته باشند. مثلا پراپرتی Email  در ویو مدل‌ها نام‌های متفاوتی داشته باشند (مثل EmailAddress  ، Email  ، ContactMail  و ...). با اینکار در زمان Postback  احتمال اینکه فیلدهای مشترک اتوماتیک پر شده به ما نمایش داده باشند صفر خواهد شد.

نکته چهارم : حواستان باشد پس از انجام عملیات مرتبط با هر فرم در اکشن متد مربوط به آن (مثلا ارسال ایمیل، ثبت در بانک یا ...) در صورتی که عملیات با موفقیت انجام شد حتما ModelState  را clear کنید. با اینکار پس از Post-back  فیلدهای پارشال‌ها خالی میشوند.

نکته پنجم : میتوانید به سادگی مدیریت خطا را به کمک جی کوئری انجام دهید؛ مثلا فرض کنید میخواهیم اگر ایمیل کاربر برای دریافت خبرنامه با موفقیت ثبت شد، پیامی مبنی بر موفقیت برای وی بفرستیم؛ اکشن متد HttPost مربوط به  Subscriber  را به شکل زیر تکمیل میکنیم : 

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult Subscribers(SubscriberVM model, string submitValue)
        {
            if (submitValue == "ثبت ایمیل")
            {                
                if (ModelState.IsValid)
                {
                    Subscriber mail = new Subscriber() { Email = model.EmailSubscriber, IsActive = true };
                    context.Subscribers.Add(mail);
                    context.SaveChanges();
                    ViewBag.info = "ایمیل شما با موفقیت ثبت شد.";
                    ViewBag.color = "alert-success";
                    ModelState.Clear();
                }
            }
            else
            {
                ModelState.Clear();
            }
            
            return PartialView("_Subscribers ");
        }

در انتهای پارشال _Subscriber هم چند خط کد زیر را مینویسیم :

@if (!String.IsNullOrEmpty(ViewBag.info))
{
    <div id="info" style="position: fixed; bottom: 0; right: 0; margin-right: 1%;">

        <div class="alert @ViewBag.color alert-dismissable">
            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
            <strong> @ViewBag.info</strong>
        </div>

    </div>
    <script>
        $(function () {
            $("#info").fadeOut(15000);
        });
    </script>
}


نتیجه این خواهد بود که پس از PostBack در صورت موفقیت تصویر زیر را خواهیم دید و 15 ثانیه المان سبزرنگ بوت استرپِ زیر نمایش داده خواهد شد.

این روش نوعی مدیریت میان اکشن متدهای دارای ویژگی HttpPost است و همانطور که گفتیم به علت اینکه پس از Post-Back نیاز به ساختار به هم نخورده‌ی صفحه‌ی قبلی داریم، نمیتوانستیم به شکل صریح، اکشن متد برای Html.BeginForm تعریف کنیم تا این دردسر‌ها را نداشته باشیم.

حین نوشتن این مقاله به علت وجود if ‌های تو در تو، امیدوار بودم که روش‌های بهتری برای اینکار موجود باشند و هنوز هم امیدوارم نظرات شما چنین چیزی را نشان دهد. 

نظرات مطالب
C# 7 - Pattern matching and switch expressions
C# 7.1 - Pattern-Matching with Generics

C# 7.1 پشتیبانی بهتری از pattern-matching را جهت کار با Generics ارائه داده‌است.
public class Car {}
public class SportsCar : Car
{
   public string Color { get; set; }
}
در اینجا یک کلاس پایه خودرو و سپس یک کلاس مشتق شده‌ی خودرو‌های ورزشی را داریم. اکنون در جائی از برنامه می‌خواهیم متد راندن این خودروها را تعریف کنیم:
public static void Run<T>(T car) where T : Car
{
   if (car is SportsCar sportsCar)
   {
   }

   switch (car)
   {
      case SportsCar sCar:
      break;
   }
}
در اینجا نوع خودرو به صورت جنریک تعریف شده‌است و سپس با استفاده از قابلیت‌های pattern-matching سعی در انطباق با آن‌ها را داریم. کامپایل این قطعه کد در C# 7.0 با خطای کامپایلر ذیل متوقف می‌شود:
 An expression of type "T" cannot be handled by a pattern of type "SportsCar"

اگر این قطعه کد را بخواهیم با C# 7.0 کامپایل کنیم نیاز است ابتدا شیء دریافتی به object تبدیل شود و سپس کار pattern-matching با موفقیت صورت خواهد گرفت:
public static void Run<T>(T car) where T : Car
{
   if ((object)car is SportsCar sportsCar)
   {
   }

   switch ((object)car)
   {
      case SportsCar sCar:
      break;
   }
}
این محدودیت در C# 7.1 برطرف شده‌است و دیگر نیازی به این cast اضافه نیست و می‌توان (object) را از قطعه کد فوق حذف کرد.
مطالب
چند نکته‌ی کاربردی در #C
استفاده از Tuple‌ها جهت مقدار برگشتی یک متد

اکثر مواقع برنامه نویسان برای بازگشت چند مقدار توسط یک متد، به روش‌هایی مثل تعریف کلاس‌های POCO یا پارامترهایی از نوع out متوسل می‌شوند. به وسیله‌ی Tuple‌ها می‌توان چند مقدار مختلف را به عنوان خروجی متد بازگشت داد:
private Tuple<string, string, int> GetPersonInfo()
{
     return new Tuple<string, string, int>("Steve", "Jobs", 56);
}
همچنین از Tuple‌ها می‌توان برای پاس دادن یکباره پارامترها به متد استفاده کرد و در مواقعی مانند ارسال پارامتر به Thread‌ها که در حالت عادی یک پارامتر را به عنوان ورودی قبول می‌کنند، کاربردی خواهند بود.


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

اکثر برنامه نویسان، در متدهایی که لیستی از مقادیر را بازگشت می‌دهند، از یک متغییر موقتی استفاده می‌کنند:
private IEnumerable<int> GetNumbers()
{
   var result = new List<int>();

   for (int i = 0; i <= 100; i++)
      result.Add(i);

   return result;
}
اما باید دانست که الزاما نیازی به انجام این کار نیست و به وسیله‌ی کلیدواژه‌ی yield می‌توان مقادیر را همزمان با تولید آنها در بدنه متد به عنوان خروجی متد بازگشت داد و به این ترتیب به مصرف حافظه‌ی کمتری رسید:
private IEnumerable<int> GetNumbers()
{
   for (int i = 0; i <= 100; i++)
   {
        yield return i;
   }
}

ملزم کردن نوع پایه یک کلاس Generic به رعایت قوانین پیاده سازی خاص

Generic‌ها میتوانند عملکرد یکسانی را برای نوع‌های داده‌ای متفاوت، پیاده سازی کنند. با توجه به ماهیت Generic‌ها ممکن است در سناریوهایی لازم باشد تا نوع داده‌ی اولیه‌ای که قرار است Generic پیاده سازی شود، از قوانین پیاده سازی خاصی پیروی کند. به صورت زیر می‌توان نوع پایه‌ی یک Generic را ملزم به رعایت قوانین خاص پیاده سازی به واسطه یک Interface کرد:
public interface ICar
{
   string GetName();
   string GetManufacturerCompany();
}

private class GenricClass<T> where T : ICar
{
}
نمونه‌ی استفاده:
public class Audi : ICar
{
   public string GetName()
   {
      throw new NotImplementedException();
   }

   public string GetManufacturerCompany()
   {
      throw new NotImplementedException();
   }
}

private static void Main(string[] args)
{
   var invalidTest = new GenricClass<int>();
   var validTest = new GenricClass<Audi>();
}
اشتراک‌ها
تولید کد اتوماتیک MVVM با Roslyn
اگر با MVVM کار میکنید و از فریمورک‌های آماده استفاده نمی‌کنید حتما پیاده سازی تکراری INotifyPropertyChanged و RealyCommand و ViewModelBase شما را خسته کرده است. کامپایلر Roslyn به شما اجازه میدهد که به سادگی امکانات Refactoring موجود در Visual Studio را سفارشی سازی کرده و بسته به نیاز خود Refactoring‌های جدید بسازید تا در زمان کدنویسی شما صرفه جویی شود. در این مقاله با نحوه ساخت چند نمونه Refactoring سفارشی آشنا می‌شوید.


تولید کد اتوماتیک MVVM با Roslyn
مطالب
آشنایی با 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 به پایان رسید.
ادامه‌ی مطالب بعد از تکمیل هر بخش در دسترس دوستان قرار خواهد گرفت.
مطالب
React 16x - قسمت 6 - کامپوننت‌ها - بخش 3 - یک تمرین
در این قسمت می‌خواهیم دانسته‌های 5 قسمت قبل را در طی یک تمرین کنار هم قرار داده و مرور کنیم.


برپایی ساختار ابتدایی پروژه‌ی تمرین

ابتدا یک پروژه‌ی جدید React را ایجاد می‌کنیم:
> create-react-app sample-05
> cd sample-05
> npm start
سپس بسته‌های بوت استرپ و font-awesome را نیز در آن نصب می‌کنیم:
> npm install --save bootstrap
> npm install --save font-awesome

در ادامه نیاز است فایل‌های CSS این کتابخانه‌ها و قلم‌های وب را import کنیم. به همین جهت ابتدای فایل index.js را به نحو زیر ویرایش خواهیم کرد:
import "bootstrap/dist/css/bootstrap.css";
import "font-awesome/css/font-awesome.css";
در نهایت کار مدیریت این فایل‌ها و قرار دادن آن‌ها در بسته‌ی نهایی برنامه، توسط webpack به صورت خودکار انجام می‌شود.

همچنین به فایل index.css هم مراجعه کرده و یک padding را به بالای صفحه اضافه می‌کنیم؛ تا اطلاعات نمایش داده شده، با کمی فاصله از لبه‌ی مرورگر رندر شوند:
body {
  margin: 0;
  padding: 20px 0 0 0;
  font-family: sans-serif;
}

پس از نصب و import این کتابخانه‌های ثالث، به فایل App.js مراجعه کرده و کلاس container اصلی بوت استرپ را در آن تعریف می‌کنیم تا در برگیرنده‌ی محتوای برنامه شود:
  return (
    <main className="container">
      <h1>Hello world!</h1>
    </main>
  );
همانطور که در قسمت چهارم نیز بحث شد، برای ذکر classهای عناصر در React، از خاصیت className استفاده می‌شود.


معرفی سرویس‌های داده‌ی برنامه

کدهای نهایی این قسمت را از فایل پیوست شده‌ی در انتهای مطلب، می‌توانید دریافت کنید. در اینجا یک پوشه‌ی src\services تعریف شده‌است که داخل آن دو فایل fakeGenreService.js و fakeMovieService.js قرار دارند. این فایل‌ها، منبع داده‌ی درون حافظه‌ای مثال تمرین ما هستند.
سرویس fakeGenre چنین ساختاری را دارد و ژانرهای سینمایی، مانند اکشن، کمدی و غیره در آن لیست شده‌اند:
export const genres = [
  { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
  // ...
];
این سرویس دارای متد ()getGenres، برای بازگشت لیست کامل genres است. علت ذکر خاصیت id با یک _، روش نامگذاری خاصیت id در mongo-db است.

و سرویس fakeMovie که دارای ساختار کلی زیر است، لیست 9 فیلم سینمایی را به همراه دارد:
const movies = [
  {
    _id: "5b21ca3eeb7f6fbccd471815",
    title: "Terminator",
    genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
    numberInStock: 6,
    dailyRentalRate: 2.5,
    publishDate: "2018-01-03T19:04:28.809Z"
  },

  //...
];
به علاوه این سرویس دارای متدهای ()getMovies برای دریافت لیست فیلم‌ها، getMovie(id) برای بازگشت یک فیلم خاص، saveMovie(movie) برای افزودن یک فیلم جدید به لیست و deleteMovie(id) برای حذف یک فیلم از لیست درون حافظه‌ای سرویس جاری است.


ایجاد کامپوننت Movies برای نمایش لیست فیلم‌ها در برنامه

اکنون می‌خواهیم یک کامپوننت جدید را به نام Movies در فایل جدید src\components\movies.jsx ایجاد کنیم، تا لیست فیلم‌های سرویس fakeMovieService را نمایش دهد. برای اینکار مراحل زیر را طی خواهیم کرد:
- نمایش ساده‌ی لیست فیلم‌ها توسط یک جدول. برای دریافت لیست اشیاء موجود در fakeMovieService، از متد ()getMovies آن می‌توان استفاده کرد.
- اضافه کردن یک دکمه‌ی حذف، به هر ردیف، به نحوی که با کلیک بر روی آن، آن ردیف حذف شود.
- نمایش یک پیام بالای جدول که تعداد فیلم‌های موجود در سرویس درون حافظه‌ای را نمایش می‌دهد. همچنین پس از حذف تمام ردیف‌ها، باید پیام «فیلمی موجود نیست» را نمایش دهد.

خروجی نهایی مثال ما به صورت زیر است:


و اگر تمام آیتم‌های آن‌را حذف کنیم، چنین پیامی نمایش داده می‌شود:


پس از ایجاد فایل خالی جدید movies.jsx در پوشه‌ی جدید components، با استفاده از «simple react snippets» نصب شده‌ی در VSCode، یکبار imrc را تایپ کرده (مخفف import react component است) و سپس دکمه‌ی tab را فشار می‌دهیم، در آخر اینکار را برای cc نیز تکرار می‌کنیم (مخفف create class است) تا importها و سپس ساختار ابتدایی کامپوننت React ما تشکیل شوند. نام این کامپوننت را هم Movies که با حرف بزرگ شروع می‌شود، وارد می‌کنیم.

اکنون مجددا به App.js مراجعه می‌کنیم و بجای Hello world ای که نمایش دادیم، کامپوننت Movies را اضافه می‌کنیم. برای این منظور ابتدا import آن‌را به ابتدای فایل اضافه می‌کنیم:
import Movies from "./components/movies";
سپس متد return آن‌را جهت درج المان کامپوننت Movies اصلاح خواهیم کرد:
return (
    <main className="container">
      <Movies />
    </main>
  );


دریافت لیست اشیاء فیلم‌ها از سرویس fakeMovieService

برای دریافت لیست اشیاء فیلم‌ها، ابتدا تعریف سرویس آن‌را به ابتدای کامپوننت Movies اضافه می‌کنیم:
 import { getMovies } from "../services/fakeMovieService";
در اینجا از {} استفاده شده، چون یک named export را import کرده‌ایم.

سپس خاصیت state را جهت تعریف خاصیت movies که با متد ()getMovies سرویس fakeMovieService مقدار دهی می‌شود، به نحو زیر تکمیل می‌کنیم:
 state = {
    movies: getMovies()
  };
البته این روش مقدار دهی اولیه‌ی خاصیت state، برای دریافت اطلاعات سرویس‌ها، هرچند در اینجا بدون مشکل کار می‌کند، اما بهتر است توسط component life cycle hooks مدیریت شود که در قسمت‌های بعدی بیشتر به جزئیات آن‌ها خواهیم پرداخت.


نمایش لیست فیلم‌ها، به همراه مدیریت حذف هر ردیف

در ادامه، کدهای کامل و تکمیل شده‌ی این کامپوننت را ملاحظه می‌کنید:
import React, { Component } from "react";

import { getMovies } from "../services/fakeMovieService";

class Movies extends Component {
  state = {
    movies: getMovies()
  };

  handleDelete = movie => {
    const movies = this.state.movies.filter(m => m._id !== movie._id);
    this.setState({ movies });
  };

  render() {
    const { length: count } = this.state.movies;

    if (count === 0) return <p>There are no movies in the database.</p>;

    return (
      <React.Fragment>
        <p>Showing {count} movies in the database.</p>
        <table className="table">
          <thead>
            <tr>
              <th>Title</th>
              <th>Genre</th>
              <th>Stock</th>
              <th>Rate</th>
              <th />
            </tr>
          </thead>
          <tbody>
            {this.state.movies.map(movie => (
              <tr key={movie._id}>
                <td>{movie.title}</td>
                <td>{movie.genre.name}</td>
                <td>{movie.numberInStock}</td>
                <td>{movie.dailyRentalRate}</td>
                <td>
                  <button
                    onClick={() => this.handleDelete(movie)}
                    className="btn btn-danger btn-sm"
                  >
                    Delete
                  </button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </React.Fragment>
    );
  }
}

export default Movies;
توضیحات:
همانطور که در ابتدای بحث نیز ذکر شد، هدف از این تمرین، مرور قسمت‌های قبل است و تمام نکات زیر را در قسمت‌های پیشین، با جزئیات بیشتری بررسی کرده‌ایم:

- ابتدا خاصیت state و سپس خاصیت movies شیء منتسب به آن، با لیست فیلم‌های موجود در سرویس مرتبط، مقدار دهی شده‌اند.
- سپس در ابتدای متد render، کار رندر شرطی انجام شده‌است. اگر تعداد فیلم‌های دریافتی صفر بود، پیام «فیلمی در بانک اطلاعاتی موجود نیست» نمایش داده می‌شود و در غیراینصورت، جدول اصلی بوت استرپی برنامه رندر خواهد شد.
در اینجا چون از خاصیت طول آرایه‌ی فیلم‌ها در چندین قسمت قرار است استفاده شود، آن‌را توسط Object Destructuring به یک متغیر نسبت داده‌ایم. همچنین توسط یک نام مستعار هم خاصیت length را با نام جدید count استفاده می‌کنیم.
- در ادامه بازگشت React.Fragment را مشاهده می‌کنید. علت اینجا است که نمی‌خواهیم div اضافه‌تری را در UI رندر کنیم. React.Fragment سبب می‌شود تا بتوانیم چندین فرزند را به المان جاری تبدیل شده‌ی به کدهای جاوا اسکریپتی اضافه کنیم، بدون اینکه خودش به المانی ترجمه شود.
- پس از return، یک () قابل مشاهده‌است. چون خروجی return ما چند سطری است، اگر در سطری که return قرار می‌گیرد، اطلاعاتی درج نشود، موتور جاوا اسکریپت آن‌را با یک سمی‌کالن خاتمه خواهد داد! و دیگر سطرهای بعدی دیده نمی‌شوند و پردازش نخواهند شد. به همین جهت از روش ذکر یک () پس از return در فایل‌های jsx زیاد استفاده می‌شود.
- در ابتدای return، همان خاصیت count را نمایش می‌دهیم.
- سپس کار رندر جدول اصلی برنامه که با کلاس‌های جداول بوت استرپ نیز مزین شده، انجام شده‌است. در React برای عدم تداخل ویژگی class با نام از پیش رزرو شده‌ی class، از خاصیت className برای ذکر کلاس‌های CSSای استفاده می‌شود.
- قسمت thead این جدول مشخص است و سرستو‌ن‌های جدول را مشخص می‌کند.
- پس از آن نیاز است ردیف‌های جدول را رندر کنیم. این‌کار را توسط متد Array.map، با نگاشت هر آیتم آرایه‌ی this.state.movies، به یک tr جدول انجام داده‌ایم.
- React برای اینکه بتواند DOM مجازی خودش را کنترل کند، نیاز دارد عناصر موجود در آن‌را به صورت منحصربفردی تشخص دهد. به همین جهت در اینجا ذکر key را بر روی المان tr که با movie._id مقدار دهی شده‌است، مشاهده می‌کنید.
- رندر مقادیر سلو‌ل‌های ردیف‌ها توسط درج {} و سپس ذکر مقداری از شیء movie دریافتی توسط متد Array.map انجام می‌شود.
- در اینجا ستون رندر دکمه‌ی Delete را نیز مشاهده می‌کنید. برای مدیریت this در آن و دسترسی به شیء movie جاری (ارسال پارامتر به رویداد گردان آن) و همچنین دسترسی به شیء this کلاس جاری برای کار با آرایه‌ی this.state.movies، از روش arrow functions برای تعریف رویدادگردان onClick استفاده کرده‌ایم.
- در متد handleDelete، یک آرایه‌ی جدید را که id ردیف‌های آن با id شیء ردیف انتخابی یکی نیست، بازگشت می‌دهیم. انتساب این آرایه‌ی جدید به آرایه‌ی this.state.movies، تغییری را در برنامه‌های React ایجاد نمی‌کند. در اینجا باید توسط متد this.setState که از کلاس پایه‌ی extends Component دریافت می‌شود، خاصیت movies را بازنویسی کرد تا React از تغییرات مطلع شده و DOM مجازی جدیدی را با مقایسه‌ی با نمونه جدید، محاسبه کرده و به DOM اصلی، جهت به روز رسانی UI اعمال کند.
- البته در اینجا this.setState({ movies }) را بجای this.setState({ movies: movies }) مشاهده می‌کنید. علت اینجا است که اگر عبارات key و value یکی باشند، می‌توان تنها همان عبارت key را جهت حذف تکرار واژه‌ها، ذکر کرد.



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: sample-05.zip
مطالب
روش استفاده‌ی از jQuery در برنامه‌های AngularJS 2.0
استفاده‌ی گسترده‌ی از jQuery به همراه برنامه‌های AngularJS 2.0 ایده‌ی خوبی نیست؛ زیرا jQuery و کدهای آن، ارتباط تنگاتنگی را بین DOM و JavaScript برقرار می‌کنند که برخلاف رویه‌ی فریم‌ورک‌های MVC است. اما با این حال استفاده‌ی از افزونه‌های بی‌شمار jQuery در برنامه‌های AngularJS 2.0، جهت غنا بخشیدن به ظاهر و همچنین کاربردپذیری برنامه، یکی از استفاده‌های پذیرفته شده‌ی آن است.
روش استفاده‌ی از jQuery نیز در حالت کلی همانند مطلب «استفاده از کتابخانه‌های ثالث جاوا اسکریپتی در برنامه‌های AngularJS 2.0» است؛ اما به همراه چند نکته‌ی اضافه‌تر مانند محل فراخوانی و دسترسی به DOM، در کدهای یک کامپوننت.


هدف: استفاده از کتابخانه‌ی Chosen

می‌خواهیم جهت غنی‌تر کردن ظاهر یک دراپ داون در برنامه‌های AngularJS 2.0، از یک افزونه‌ی بسیار معروف jQuery به نام Chosen استفاده کنیم.


تامین پیشنیازهای اولیه

می‌توان فایل‌های این کتابخانه را مستقیما از GitHub دریافت و به پروژه اضافه کرد. اما بهتر است این‌کار را توسط bower مدیریت کنیم. این کتابخانه هنوز دارای بسته‌ی رسمی npm نیست (و بسته‌ی chosen-npm که در مخزن npm وجود دارد، توسط این تیم ایجاد نشده‌است). اما همانطور که در مستندات آن نیز آمده‌است، توسط دستور ذیل نصب می‌شود:
bower install chosen
برای مدیریت این مساله در ویژوال استودیو، به منوی project و گزینه‌ی add new item مراجعه کرده و bower را جستجو کنید:


در اینجا نام پیش فرض bower.json را پذیرفته و سپس محتوای فایل ایجاد شده را به نحو ذیل تغییر دهید:
{
    "name": "asp-net-mvc5x-angular2x",
    "version": "1.0.0",
    "authors": [
        "DNT"
    ],
    "license": "MIT",
    "ignore": [
        "node_modules",
        "bower_components"
    ],
    "dependencies": {
        "chosen": "1.4.2"
    },
    "devDependencies": {
    }
}
ساختار این فایل هم بسیار شبیه‌است به ساختار package.json مربوط به npm. در اینجا کتابخانه‌ی chosen در قسمت لیست وابستگی‌ها اضافه شده‌است. با ذخیره کردن این فایل، کار دریافت خودکار بسته‌های تعریف شده، آغاز می‌شود و یا کلیک راست بر روی فایل bower.json دارای گزینه‌ی restore packages نیز هست.
پس از دریافت خودکار chosen، بسته‌ی آن‌را در مسیر bower_components\chosen واقع در ریشه‌ی پروژه می‌توانید مشاهده کنید.


استفاده از jQuery و chosen به صورت untyped

ساده‌ترین و متداول‌ترین روش استفاده از jQuery و افزونه‌های آن شامل موارد زیر هستند:
الف) تعریف مداخل مرتبط با آن‌ها در فایل index.html
<script src="~/node_modules/jquery/dist/jquery.min.js"></script>
<script src="~/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>

<script src="~/bower_components/chosen/chosen.jquery.min.js"></script>
<link href="~/bower_components/chosen/chosen.min.css" rel="stylesheet" type="text/css" />
که در اینجا jQuery و بوت استرپ و chosen به همراه فایل css آن اضافه شده‌اند.
ب) تعریف jQuery به صورت untyped
declare var jQuery: any;
همینقدر که این یک سطر را به ابتدای ماژول خود اضافه کنید، امکان دسترسی به تمام امکانات جی‌کوئری را خواهید یافت. البته بدون intellisense و بررسی نوع‌های پارامترها؛ چون نوع آن، any یا همان حالت پیش فرض جاوا اسکریپت تعریف شده‌است.


محل صحیح فراخوانی متدهای مرتبط با jQuery

در تصویر ذیل، چرخه‌ی حیات یک کامپوننت را مشاهده می‌کنید که با تعدادی از آن‌ها پیشتر آشنا شده‌‌ایم:

روش متداول استفاده از jQuery، فراخوانی آن پس از رخداد document ready است. در اینجا معادل این رخداد، hook ویژ‌ه‌ای به نام ngAfterViewInit است. بنابراین تمام فراخوانی‌های jQuery را باید در این متد انجام داد.
همچنین جی‌کوئری نیاز دارد تا بداند هم اکنون قرار است با چه المانی کار کنیم و کامپوننت بارگذاری شده کدام است. برای این منظور، یکی از سرویس‌های توکار AngularJS 2.0 را به نام ElementRef، به سازنده‌ی کلاس تزریق می‌کنیم. توسط خاصیت this._el.nativeElement آن می‌توان به المان ریشه‌ی کامپوننت جاری دسترسی یافت.
constructor(private _el: ElementRef) {
}


تهیه‌ی کامپوننت نمایش یک دراپ داون مزین شده با chosen

در ادامه قصد داریم نکاتی را که تاکنون مرور کردیم، به صورت یک مثال پیاده سازی کنیم. به همین جهت فایل جدید using-jquery-addons.component.ts را به پروژه اضافه کنید به همراه فایل قالب آن به نام using-jquery-addons.component.html؛ با این محتوا:
الف) کامپوننت using-jquery-addons.component.ts
import { Component, ElementRef, AfterViewInit } from "@angular/core";

declare var jQuery: any; // untyped

@Component({
    templateUrl: "app/using-jquery-addons/using-jquery-addons.component.html"
})
export class UsingJQueryAddonsComponent implements AfterViewInit {

    dropDownItems = ["First", "Second", "Third"];
    selectedValue = "Second";

    constructor(private _el: ElementRef) {
    }

    ngAfterViewInit() {
        jQuery(this._el.nativeElement)
            .find("select")
            .chosen()
            .on("change", (e, args) => {
                this.selectedValue = args.selected;
            });
    }
}

ب) قالب using-jquery-addons.component.html
<select>
    <option *ngFor="let item of dropDownItems"
            [value]="item"
            [selected]="item == selectedValue">
        {{item}} option
    </option>
</select>

<h4> {{selectedValue}}</h4>
با این خروجی


توضیحات

کلاس UsingJQueryAddonsComponent، اینترفیس AfterViewInit را پیاده سازی کرده‌است؛ تا توسط متد ngAfterViewInit بتوانیم با عناصر DOM کار کنیم. هرچند در کل اینکار باید صرفا محدود شود به مواردی مانند مثال جاری و در حد آغاز یک افزونه‌ی jQuery و اگر قرار است تغییراتی دیگری صورت گیرند بهتر است از همان روش binding توکار AngularJS 2.0 استفاده کرد.
در سازنده‌ی کلاس، سرویس ElementRef تزریق شده‌است تا توسط خاصیت this._el.nativeElement آن بتوان به المان ریشه‌ی کامپوننت جاری دسترسی یافت. به همین جهت است که پس از آن از متد find، برای یافتن دراپ داون استفاده شده‌است و سپس chosen به نحو متداولی به آن اعمال گردیده‌است.
در اینجا هر زمانیکه یکی از آیتم‌های دراپ داون انتخاب شوند، مقدار آن به خاصیت selectedValue انتساب داده شده و این انتساب سبب فعال سازی binding و نمایش مقدار آن در ذیل دراپ داون می‌گردد.
در قالب این کامپوننت هم با استفاده از ngFor، عناصر دراپ داون از آرایه‌ی dropDownItems تعریف شده در کلاس کامپوننت، تامین می‌شوند. متغیر محلی item تعریف شده‌ی در اینجا، در محدودی همین المان قابل دسترسی است. برای مثال از آن جهت تنظیم دومین آیتم لیست به صورت انتخاب شده، در حین اولین بار نمایش view استفاده شده‌است.


استفاده از jQuery و chosen به صورت typed

کتابخانه‌ی jQuery در مخزن کد https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/jquery دارای فایل d.ts. خاص خود است. برای نصب آن می‌توان از روش ذیل استفاده کرد:
npm install -g typings
typings install jquery --save --ambient
پس از افزودن فایل typings این کتابخانه، در ابتدای فایل main.ts یک سطر ذیل را اضافه کنید:
 /// <reference path="../typings/browser/ambient/jquery/index.d.ts" />
اینکار سبب خواهد شد تا intellisense درون ویژوال استودیو بتواند مداخل متناظر را یافته و راهنمای مناسبی را ارائه دهد.

در ادامه به فایل using-jquery-addons.component.ts مراجعه کرده و تغییر ذیل را اعمال کنید:
// declare var jQuery: any; // untyped
declare var jQuery: JQueryStatic; // typed
فایل d.ts. اضافه شده، امکان استفاده‌ی از نوع جدید JQueryStatic را مهیا می‌کند. پس از آن در کدهای تعریف شده، chosen به رنگ قرمز در می‌آید، چون در تعاریف نوع دار jQuery، این افزونه وجود خارجی ندارد. برای رفع این مشکل، فایل typings/browser/ambient/jquery/index.d.ts را گشوده و سپس به انتهای آن، تعریف chosen را به صورت دستی اضافه کنید:
interface JQuery {
   //...
   chosen(options?:any):JQuery;
}
declare module "jquery" {
   export = $;
}
به این ترتیب این متد به عنوان جزئی از متدهای زنجیروار jQuery، شناسایی شده و قابل استفاده خواهد شد.


کدهای کامل این پروژه را از اینجا می‌توانید دریافت کنید.
بازخوردهای دوره
ارتباطات بلادرنگ و SignalR
در مقاله زیر هم با استفاده از کتابخانه  SignalR و کلاس SqlDepedency و رویداد OnChange این کلاس بخوبی این ارتباط بلادرنگ پیاده سازی شده
لینک مقاله

من دقیقا مثال بالا را پیاده سازی کردم اما جواب نداد

 قبلا شنیده بودم که از کلاس Sqldepedency تنها میتوان در برنامه‌های ویندوزی استفاده کرد و نه وب !
و در برنامه‌های مبتنی بر وب تنها از SqlCachedepedency

آیا هنوز هم اینگونه هست ؟

مسیرراه‌ها
ASP.NET MVC