InversifyJS is a lightweight inversion of control (IoC) container for TypeScript and JavaScript apps. A IoC container uses a class constructor to identify and inject its dependencies. InversifyJS has a friendly API and encourage the usage of the best OOP and IoC practices.
اشتراکها
پیشتر مطلبی را در مورد ایجاد Drop Down Listهای به هم پیوسته توسط jQuery Ajax در این سایت مطالعه کرده بودید. شبیه به همان مطلب را اینبار قصد داریم توسط Kendo UI پیاده سازی کنیم.
مدلهای برنامه
در اینجا قصد داریم لیست گروهها را به همراه محصولات مرتبط با آنها، توسط دو drop down list نمایش دهیم:
از ویژگی JsonIgnore جهت عدم درج لیست محصولات، در خروجی JSON نهایی تولیدی گروهها، استفاده شدهاست.
منبع داده JSON سمت سرور
پس از مشخص شدن مدلهای برنامه، اکنون توسط دو اکشن متد، لیست گروهها و همچنین لیست محصولات یک گروه خاص را با فرمت JSON بازگشت میدهیم:
بار اولی که صفحه بارگذاری میشود، توسط یک درخواست Ajax ایی، لیست گروهها دریافت خواهد شد. سپس با انتخاب یک گروه، اکشن متد GetProducts جهت بازگرداندن لیست محصولات آن گروه، فراخوانی میگردد.
در اینجا به عمد از JsonConvert.SerializeObject استفاده شدهاست تا ویژگی JsonIgnore کلاس گروهها، توسط کتابخانهی JSON.NET مورد استفاده قرار گیرد (ASP.NET MVC برخلاف ASP.NET Web API به صورت پیش فرض از JSON.NET استفاده نمیکند).
کدهای سمت کاربر برنامه
کدهای جاوا اسکریپتی Kendo UI را جهت تعریف دو drop down list به هم مرتبط و آبشاری، در ادامه ملاحظه میکنید:
دراپ داون اول، به صورت متداولی تعریف شدهاست. ابتدا فیلدهای Text و Value هر ردیف آن مشخص و سپس منبع داده آن به اکشن متد GetCategories تنظیم گردیدهاست. به این ترتیب با اولین بار مشاهدهی صفحه، این دراپ داون پر خواهد شد.
سپس دراپ دوم که وابستهاست به دراپ داون اول، با این نکات طراحی شدهاست:
الف) خاصیت autoBind آن به false تنظیم شدهاست. به این ترتیب این دراپ داون در اولین بار نمایش صفحه، به سرور جهت دریافت اطلاعات مراجعه نخواهد کرد.
ب) خاصیت cascadeFrom آن به id دراپ داون اول تنظیم شدهاست.
ج) در منبع دادهی آن دو تغییر مهم وجود دارند:
- خاصیت serverFiltering به true تنظیم شدهاست. این مورد سبب خواهد شد تا آیتم گروه انتخاب شده، به سرور ارسال شود.
- خاصیت data نیز تنظیم شدهاست. این مورد پارامتر categoryId اکشن متد GetProducts را تامین میکند و مقدار آن از مقدار انتخاب شدهی دراپ داون اول دریافت میگردد.
اگر برنامه را اجرا کنیم، برای بار اول لیست گروهها دریافت خواهند شد:
سپس با انتخاب یک گروه، لیست محصولات مرتبط با آن در دراپ داون دوم ظاهر میگردند:
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید.
مدلهای برنامه
در اینجا قصد داریم لیست گروهها را به همراه محصولات مرتبط با آنها، توسط دو drop down list نمایش دهیم:
public class Category { public int CategoryId { set; get; } public string CategoryName { set; get; } [JsonIgnore] public IList<Product> Products { set; get; } } public class Product { public int ProductId { set; get; } public string ProductName { set; get; } }
منبع داده JSON سمت سرور
پس از مشخص شدن مدلهای برنامه، اکنون توسط دو اکشن متد، لیست گروهها و همچنین لیست محصولات یک گروه خاص را با فرمت JSON بازگشت میدهیم:
using System.Linq; using System.Text; using System.Web.Mvc; using KendoUI12.Models; using Newtonsoft.Json; namespace KendoUI12.Controllers { public class HomeController : Controller { public ActionResult Index() { return View(); // shows the page. } [HttpGet] public ActionResult GetCategories() { return new ContentResult { Content = JsonConvert.SerializeObject(CategoriesDataSource.Items), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } [HttpGet] public ActionResult GetProducts(int categoryId) { var products = CategoriesDataSource.Items .Where(category => category.CategoryId == categoryId) .SelectMany(category => category.Products) .ToList(); return new ContentResult { Content = JsonConvert.SerializeObject(products), ContentType = "application/json", ContentEncoding = Encoding.UTF8 }; } } }
در اینجا به عمد از JsonConvert.SerializeObject استفاده شدهاست تا ویژگی JsonIgnore کلاس گروهها، توسط کتابخانهی JSON.NET مورد استفاده قرار گیرد (ASP.NET MVC برخلاف ASP.NET Web API به صورت پیش فرض از JSON.NET استفاده نمیکند).
کدهای سمت کاربر برنامه
کدهای جاوا اسکریپتی Kendo UI را جهت تعریف دو drop down list به هم مرتبط و آبشاری، در ادامه ملاحظه میکنید:
<!--نحوهی راست به چپ سازی --> <div class="k-rtl k-header demo-section"> <label for="categories">گروهها: </label><input id="categories" style="width: 270px" /> <label for="products">محصولات: </label><input id="products" disabled="disabled" style="width: 270px" /> </div> @section JavaScript { <script type="text/javascript"> $(function () { $("#categories").kendoDropDownList({ optionLabel: "انتخاب گروه...", dataTextField: "CategoryName", dataValueField: "CategoryId", dataSource: { transport: { read: { url: "@Url.Action("GetCategories", "Home")", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET' } } } }); $("#products").kendoDropDownList({ autoBind: false, // won’t try and read from the DataSource when it first loads cascadeFrom: "categories", // the id of the DropDown you want to cascade from optionLabel: "انتخاب محصول...", dataTextField: "ProductName", dataValueField: "ProductId", dataSource: { // When the serverFiltering is disabled, then the combobox will not make any additional requests to the server. serverFiltering: true, // the DataSource will send filter values to the server transport: { read: { url: "@Url.Action("GetProducts", "Home")", dataType: "json", contentType: 'application/json; charset=utf-8', type: 'GET', data: function () { return { categoryId: $("#categories").val() }; } } } } }); }); </script> <style scoped> .demo-section { width: 100%; height: 100px; } </style> }
سپس دراپ دوم که وابستهاست به دراپ داون اول، با این نکات طراحی شدهاست:
الف) خاصیت autoBind آن به false تنظیم شدهاست. به این ترتیب این دراپ داون در اولین بار نمایش صفحه، به سرور جهت دریافت اطلاعات مراجعه نخواهد کرد.
ب) خاصیت cascadeFrom آن به id دراپ داون اول تنظیم شدهاست.
ج) در منبع دادهی آن دو تغییر مهم وجود دارند:
- خاصیت serverFiltering به true تنظیم شدهاست. این مورد سبب خواهد شد تا آیتم گروه انتخاب شده، به سرور ارسال شود.
- خاصیت data نیز تنظیم شدهاست. این مورد پارامتر categoryId اکشن متد GetProducts را تامین میکند و مقدار آن از مقدار انتخاب شدهی دراپ داون اول دریافت میگردد.
اگر برنامه را اجرا کنیم، برای بار اول لیست گروهها دریافت خواهند شد:
سپس با انتخاب یک گروه، لیست محصولات مرتبط با آن در دراپ داون دوم ظاهر میگردند:
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید.
اشتراکها
پیاده سازی چارت ها با Google Charts
If you are working for analytics project, you need a rich chart system
to display big data results. Google is providing us a powerful chart
tools that you can implement charts very simple Demo
اشتراکها
Binary Serialization سریع با Bebop
اشتراکها
معرفی SQL Server بر روی Linux
در راهنمای کدنویسی Angular توصیه شده از اینترفیسها برای تعریف نوع مدلها استفاده شود:
در کل سلیقهای است و بهتر است یکنواختی و یکدستی کد مدنظر باشد.
Consider using a class instead of an interface for services and declarables (components, directives, and pipes)
Consider using an interface for data models
البته این مورد موافقها و مخالفهایی هم دارد.در کل سلیقهای است و بهتر است یکنواختی و یکدستی کد مدنظر باشد.
مطالب
Microbenchmark
What Is Micro Benchmark? Micro benchmark is a benchmark designed to measure the performance of a very small and specific piece of code. (^)
البته این موضوع امروزه بیشتر در Java مطرحه تا دات نت (^ و ^ و ^) اما مفاهیم اصلی مختص یک زبان یا پلتفرم نیست.
وقتی در مورد آزمایش بار برای مقایسه کارایی کلاس StrigBuilder تحقیق میکردم به مطلب جالبی برخورد کردم. خلاصش این میشه که برای تست بار قسمتهایی از کدتون میتونین زمان موردنیاز برای اجرای اون کد رو بررسی کنین و چون ممکنه انجام این کار چندین بار نیاز بشه بهتره از متد زیر برای اینکار استفاده کنین:
static void Profile(string description, int iterations, Action func) { // clean up GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); // warm up func(); var watch = Stopwatch.StartNew(); for (int i = 0; i < iterations; i++) { func(); } watch.Stop(); Console.Write(description); Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds); }
سه خط اول متد بالا برای آمادهسازی حافظه جهت اجرای تست موردنظر است. برای آشنایی بیشتر با نحوه عملکرد Garbage Collector (^ و ^ و ^) خوندن کتاب فوق العاده CLR via C# - 3rd ed رو پیشنهاد میکنم (فصلهای 21 و 22).
سپس یکبار اکشن موردنظر (که حاوی قطعه کد موردنظره) اجرا میشه تا مسائل مربوطه به بارگذاریهای اولیه در نتیجه تست تاثیر نزاره (warm up).
در نهایت هم آزمایش بار برای تعداد تکرار درخواست شده انجام میشه و زمان اجرای اون در خروجی چاپ میشه.
برای استفاده از متد فوق میشه از کد زیر استفاده کرد:
Profile("a descriptions", how_many_iterations_to_run, () => { // ... code being profiled });
و برای استفاده از این متد در آزمایش کارایی کلاس StringBuilder میشه از کدی شبیه به کد زیر استفاده کزد:
var iterations = 10000000; var testString = ".NET Tips is awesme!"; do { var sb1 = new StringBuilder(testString); var sb2 = new StringBuilder(testString) { Capacity = testString.Length * iterations }; try { Profiler.Profile("StringBuilder Profiler", iterations, () => sb1.Append(testString)); Profiler.Profile("StringBuilder Capacity Profiler", iterations, () => sb2.Append(testString)); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { Console.WriteLine("----------------------------------------------------------------"); sb1.Clear(); sb2.Clear(); } } while (Console.ReadKey(true).Key == ConsoleKey.C); // C = continue
البته برای اینکه عملیات مقدار دهی خاصیت Capacity در قسمت warm up متد profile نتایج رو تحت تاثیر قرار نده برای این تست من اون قسمت رو کامنت کردم (اگر این کار رو نکنین زمانهای بدست اومده برای هر دو مورد یکی خواهد بود). اجرای کد بالا نتایج زیر رو تو سیستم من ارائه داد:
میبینین که نتایج استفاده از متد موردبحث کمی فرق داره و افزایش کارایی در حالت استفاده از پراپرتی Capacity دیگه حدود 3 برابر نیست و حدود 2 دو برابره. البته زمان بدست اومده برای هر دو مورد نسبت به قبل کاهش داشته که بیشترش میتونه مربوطه به عدم درنظر گرفتن زمان موردنیاز برای ایجاد کلاس StringBuilder در این تست جدید باشه (چون بعید میدونم عملیات پاکسازی حافظه توسط GC تو این تست تاثیر چندانی داشته باشه). درهر حال نتایج این تست بیشتر به واقعیت نزدیکه!