اشتراک‌ها
کتابخانه jQuery Chat
  100% Javascript realtime chat like facebook/gmail web style built with jQuery UI + Node.js + Socket.IO
کتابخانه jQuery Chat
نظرات مطالب
تاثیر تعداد فونت‌های نصب شده در سیستم بر روی سرعت بارگذاری اولیه برنامه‌ها
فکر میکنم هارد ssd کمک بسیاری در بارگذاری اولیه ویژوال استدیو بکنه... چون هنگام باز شدن پروژه میزان استفاده از دیسک در تسک منیجر به 100% میرسه 
نظرات مطالب
برنامه نویسی اندروید با Xamarin.Android - قسمت اول
سلام
« ... با استفاده از Xamarin.Forms میتونیم کد رو بصورت 100% برای هر 3 پلتفرم نامبرده بکار ببریم ... »
سوال : تفاوتش با حالتهای دیگر چیست و بهتر است که برای انجام برنامه‌ها از این روش استفاده کنیم ؟
نظرات مطالب
تولید SiteMap استاندارد و ایجاد یک ActionResult اختصاصی برای Return کردن SiteMap تولید شده
این کار که 100% باید انجام بشه وگرنه بی فایدست تمام ماجرا . ممنون از آقای نصیری بابت پیوست این نکته. دوستان حتما توجه داشته باشن ....
مطالب
آموزش Linq - بخش ششم : عملگرهای پرس و جو قسمت سوم
عملگر‌های تبدیل Conversion Operator

عملگر‌های پرس و جوی تبدیل، توالی‌هایی را که از جنس <IEnumerable<T هستند، به انواع دیگر مجموعه تبدیل می‌کنند.
از عملگر‌های پرس و جوی زیر می‌توان برای تبدیل توالی‌ها استفاده کرد :
  • OfType
  • Cast
  • ToArray
  • ToList
  • ToDictionary
  • ToLookup

عملگر OfType


این عملگر عناصری از توالی را که نوع آنها را مشخص می‌کنیم باز می‌گرداند.
امضاء عملگر پرس و جوی OfType  به صورت زیر است :
 public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
همانطور که مشاهده می‌کنید توالی ورودی از یک نوع IEnumerable غیر جنریک می‌باشد. بدین معنی که عناصر توالی ورودی می‌توانند از نوع داده‌های مختلف باشند (توالی از اشیاء، از جنس Object).
در مثال زیر یک توالی IEnumerable (آرایه‌ای از اشیاء)، از عناصر با نوع داده‌های مختلفی را ایجاد کرده‌ایم. عملگر OfType در اینجا کلیه عناصر از جنس (string) را باز می‌گرداند. توالی خروجی یک نوع IEnumerable جنریک است(در این مثال <IEnumerable<List).
مثال :
IEnumerable input = new object[] { "Apple", 33, "Sugar", 44, 'a', new DateTime()};
IEnumerable<string> query = input.OfType<string>();
foreach (var item in query)
{
   Console.WriteLine(item);
}
خروجی مثال بالا :
Apple
Sugar
عملگر OfType را می‌توان به‌همراه  Strongly Type‌‌ها نیز استفاده کرد.
مثال :کد زیر یک ساختار سلسله مراتبی شیء گرا را نمایش می‌دهد:
 class Ingredient
  {
     public string Name { get; set; }
  }
  class DryIngredient : Ingredient
  {
     public int Grams { get; set; }
  }

  class WetIngredient : Ingredient
  {
     public int Millilitres { get; set; }
  }
کد زیر چگونگی استفاده از OfType را برای بدست آوردن یک زیر نوع (Subtype) مشخص، نشان می‌دهد (در این مثال، نوع WetIngredient):
IEnumerable<Ingredient> input = new Ingredient[]
{
   new DryIngredient { Name = "Flour" },
   new WetIngredient { Name = "Milk" },
   new WetIngredient { Name = "Water" }
};

IEnumerable<WetIngredient> query = input.OfType<WetIngredient>();
foreach (WetIngredient item in query)
{
   Console.WriteLine(item.Name);
}
خروجی مثال بالا :
Milk
Water

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر Cast


عملگر Cast همانند عملگر OfType رفتار می‌کند. این عملگر یک توالی ورودی را دریافت و بر اساس نوع مشخص شده، توالی خروجی را تولید می‌کند. همه‌ی عناصر توالی ورودی به نوع مشخص شده Cast می‌شوند. اما بر عکس عملگر OfType که عناصری را که با نوع داده‌ی ما سازگاری نداشت، نادیده می‌گرفت، این عملگر در صورت عدم موفقیت در عملیات تغییر نقش (Cast)، یک استثناء را پرتاب می‌کند.
مثال : 
IEnumerable input = new object[]
{
   "Apple", 33, "Sugar", 44, 'a', new DateTime()
};

IEnumerable<string> query = input.Cast<string>();
foreach (string item in query)
{
   Console.WriteLine(item);
}
با اجرای برنامه‌ی فوق، خطای زیر را مشاهده خواهید کرد:
 Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.

پیاده سازی توسط عبارت‌های جستجو


کلمه‌ی کلیدی جایگزینی برای عملگر Cast، در عبارت‌های جستجو وجود ندارد.این عملگر با استفاده از متغیر Range که در مطالب قبلی این سری معرفی شد، قابل پیاده سازی می‌باشد.
IEnumerable input = new object[]{ "Apple", "Sugar", "Flour" };
IEnumerable<string> query =
from string i in input
select i;

foreach (var item in query)
{
   Console.WriteLine(item);
}
نکته:  در مثال فوق تعریف صریح (Explicit) نوع داده، قبل از متغیر Range انجام شده است (معادل همان نوع داده در عملیات Cast).


عملگر ToArray


عملگر ToArray یک توالی ورودی را دریافت و یک توالی خروجی را به صورت آرایه تولید می‌کند. این عملگر باعث اجرای سریع پرس و جو می‌شود و رفتار پیش فرض LINQ را که اجرای با تاخیر می‌باشد، تحریف/بازنویسی (Override) می‌کند.
مثال: در این مثال یک توالی از نوع <IEnumerable<string به یک آرایه رشته‌ای تبدیل شده است (تبدیل لیست به آرایه).
 IEnumerable<string> input = new List<string> { "Apple", "Sugar", "Flour" };
string[] array = input.ToArray();

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر ToList

عملگر ToList همچون ToArray، اجرای با تاخیر را نادیده می‌گیرد. عملگر ToList همانطور که از نامش پیداست، توالی خروجی را به‌صورت لیست مهیا می‌کند.
مثال:
 IEnumerable<string> input = new[] { "Apple", "Sugar", "Flour" };
List<string> list = input.ToList();

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر ToDictionary

این عملگر توالی ورودی را به یک  دیکشنری جنریک تبدیل می‌کند (<Dictinary<TKey,TValue) .
ساده‌ترین امضاء عملگر ToDictionary، یک عبارت Lambda می‌باشد. این عبارت Lambda  نشان دهنده‌ی یک تابع است که عنصر کلید(Key) را در دیکشنری، مشخص می‌کند.
مثال:
class Recipe
{
   public int Id { get; set; }
   public string Name { get; set; }
   public int Rating { get; set; }
}

IEnumerable<Recipe> recipes = new[]
{
   new Recipe { Id = 1, Name = "Apple Pie", Rating = 5 },
   new Recipe { Id = 2, Name = "Cherry Pie", Rating = 2 },
   new Recipe { Id = 3, Name = "Beef Pie", Rating = 3 }
};

Dictionary<int, Recipe> dict = recipes.ToDictionary(x => x.Id);
foreach (KeyValuePair<int, Recipe> item in dict)
{
   Console.WriteLine($"Key={item.Key}, Recipe={item.Value}");
}
در کد بالا ، کلید دیکشنری نهایی، از نوع  int می‌باشد که بر اساس Id کلاس Recipe تنظیم شده است. مقادیر (value) دیکشنری هم همان اشیاء از جنس کلاس Recipe می‌باشند.
خروجی مثال بالا:
Key=1, Recipe=Apple Pie
Key=2, Recipe=Cherry Pie
Key=3, Recipe=Beef Pie

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر ToLookup


این عملگر رفتاری شبیه به عملگر ToDictionary را دارد، اما به جای تولید خروجی از نوع دیکشنری، نمونه‌ای از جنس ILookUp را ایجاد می‌کند.
در کد زیر خروجی ایجاد شده توسط lookup دستورالعمل‌ها (Recipes) را بر حسب  امتیاز آنها گروه بندی کرده است. در این مثال کلید، بر حسب Byte می‌باشد.
مثال :
class Recipe
{
   public int Id { get; set; }
   public string Name { get; set; }
   public byte Rating { get; set; }
}

IEnumerable<Recipe> recipes = new[]
{
   new Recipe { Id = 1, Name = "Apple Pie", Rating = 5 },
   new Recipe { Id = 1, Name = "Banana Pie", Rating = 5 },
   new Recipe { Id = 2, Name = "Cherry Pie", Rating = 2 },
   new Recipe { Id = 3, Name = "Beef Pie", Rating = 3 }
};

ILookup<byte, Recipe> look = recipes.ToLookup(x => x.Rating);
foreach (IGrouping<byte, Recipe> ratingGroup in look)
{
   byte rating = ratingGroup.Key;
   Console.WriteLine($"Rating {rating}");
   foreach (var recipe in ratingGroup)
   {
      Console.WriteLine($" - {recipe.Name}");
   }
}
خروجی مثال بالا:
 Rating 5
 - Apple Pie
 - Banana Pie
Rating 2
 - Cherry Pie
Rating 3
 - Beef Pie

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر‌های عناصر  Element Operators

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


عملگر First

این عملگر اولین عنصر توالی را باز می‌گرداند.
مثال :
Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 500}
};

Ingredient element = ingredients.First();
Console.WriteLine(element.Name);
خروجی مثال بالا :
 Sugar
امضای دیگر این متد، امکان تعریف یک شرط را مهیا می‌کند. خروجی این حالت اولین عنصری است که شرط را تامین می‌کند. در کد زیر اولین عنصری که کالری آن برابر 150 باشد به خروجی ارسال می‌شود.
Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 500}
};

Ingredient element = ingredients.First(x=>x.Calories==150);
Console.WriteLine(element.Name);
خروجی مثال بالا:
 Milk
در زمان استفاده از عملگر First، اگر توالی ورودی هیچ عنصری نداشته باشد، یک استثناء رخ خواهد داد:
 Unhandled Exception: System.InvalidOperationException: Sequence contains no elements
کد زیر نمونه‌ای از این حالت است:
Ingredient[] ingredients = { };
Ingredient element = ingredients.First();
در زمان استفاده‌ی از امضاء دیگر عملگر First، اگر هیچ عنصری شرط معرفی شده‌ی در پارامتر را تامین نکند، باز هم یک استثناء رخ خواهد داد:
 Unhandled Exception: System.InvalidOperationException: Sequence contains no matching element
کد زیر حالت فوق را نشان می‌دهد:
 Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 500}
};
Ingredient element = ingredients.First(x=>x.Calories==1500);

پیاده سازی توسط عبارت‌های جستجو

معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر FirstOrDefault

عملگر FirstOrDefalt همانند عملگر First عمل می‌کند، اما با این تفاوت که به جای پرتاب یک استثناء در شرایط معرفی شده در عملگر First، یک مقدار پیش فرض را بر اساس نوع  عناصر توالی باز می‌گرداند. در صورتیکه توالی از نوع عددی باشد، مقدار 0 و اگر عناصر توالی از انواع ارجاعی باشند، مقدار Null و برای مقادیر منطقی، ارزش False به‌عنوان مقادیر پیش فرض باز گردانده می‌شوند.
مثال :
 Ingredient[] ingredients = { };
Ingredient element = ingredients.FirstOrDefault();
Console.WriteLine(element == null);
خروجی مثال بالا :
 True
پیاده سازی حالتی که هیچ یک از عناصر با شرط عملگر کطالبقت ندارند.
Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 500}
};

Ingredient element = ingredients.FirstOrDefault(x=>x.Calories==1500);
Console.WriteLine(element==null);
خروجی مثال بالا :
 True

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


 عملگر Last

این عملگر آخرین عنصر توالی را باز می‌گرداند. همچون عملگر First، این عملگر نیز یک امضاء برای دریافت یک عبارت شرط یا پیش بینی دارد. این پیش بینی، آخرین عنصری را که شرط را تامین کند، باز می‌گرداند. باز هم مثل عملگر First، در صورتی که توالی هیچ عنصری نداشته باشد و یا عدم تامین شرط توسط عناصر توالی، استثنایی رخ خواهد داد.
مثال :
Ingredient[] ingredients =
{
   new Ingredient {Name = "Sugar", Calories = 500},
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 150},
   new Ingredient {Name = "Flour", Calories = 50},
   new Ingredient {Name = "Butter", Calories = 500}
};
Ingredient element = ingredients.Last(x=>x.Calories==500);
Console.WriteLine(element.Name);
خروجی مثال بالا :
 Flour

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر LastOrDefault

این عملگر همچون عملگر FirstOrDefault عمل می‌کند. از بروز استثناء جلوگیری کرده و مقدار پیش فرض را به خروجی ارسال می‌کند.

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر Single

عملگر Single ، تنها عنصر توالی ورودی را باز می‌گرداند.در صورتی که توالی ما بیش از یک عنصر داشته باشد و یا توالی هیچ عنصری نداشته باشد، یک استثناء رخ خواهد داد.
Unhandled Exception: System.InvalidOperationException: Sequence contains more than one matching element
Unhandled Exception: System.InvalidOperationException: Sequence contains no matching element
مثال :
Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 }
};

Ingredient element = ingredients.Single();
Console.WriteLine(element.Name);
خروجی مثال بالا :
 Sugar
عملگر Single، یک امضاء دیگر نیز دارد که یک عبارت پیش بینی را می‌پذیرد. در صورتی که بیش از یک عنصر، با پیش بینی مطابقت داشته باشد و یا هیچ عنصری شرط پیش بینی را تامین نکند، استثنائی رخ خواهد داد.
Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 },
   new Ingredient {Name = "Butter", Calories = 150},
   new Ingredient {Name = "Milk", Calories = 500}
};
Ingredient element = ingredients.Single(x => x.Calories == 150);
Console.WriteLine(element.Name);
خروجی مثال بالا :
 Butter

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر SingleOrDefault

عملگر SingleOrDefault همچون عملگر Single عمل می‌کند؛ اما با این تفاوت که اگر توالی هیچ عنصری نداشته باشد، مقدار پیش فرض نوع توالی، باز گردانده می‌شود و در صورتیکه هیچ عنصری شرط مشخص شده را تامین نکند، باز هم مقدار پیش فرض توالی، به جای رخ دادن استثناء باز گردانده می‌شود.
مثال : در این مثال هیچ عنصری با پیش بینی مشخص شده مطالبقت ندارد:
 Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 },
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 50}
};
Ingredient element = ingredients.SingleOrDefault(x => x.Calories == 9999);
Console.WriteLine(element==null);
خروجی مثال بالا :
True
توجه داشته باشید که استثنائی رخ نداده است و مقدار پیش فرض انواع ارجاعی که Null می‌باشد باز گردانده شده است.

پیاده سازی توسط عبارت‌های جستجو

معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر ElementAt


عملگر ElementAt   عنصری را در یک جایگاه مشخص شده‌ی در توالی، باز می‌گرداند.
مثال: در کد زیر سومین عنصر توالی ورودی انتخاب می‌شود:
 Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 },
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 50}
};

Ingredient element = ingredients.ElementAt(2);
Console.WriteLine(element.Name);
خروجی مثال بالا :
 Milk
باید دقت کرد که مقدار ارسالی به عملگر  ElementAt، اندیسی با نقطه‌ی آغاز صفر می‌باشد. بدین معنی که برای بدست آوردن اولین عنصر باید مقدار 0 را به عملگر ElementAt ارسال کرد. در صورتی که مقدار ارسالی با بازه اندیس‌های عناصر توالی مطابقت نداشته باشد (بزرگتر از شماره اندیس آخرین عنصر توالی باشد) یک استثناء رخ خواهد داد.
 System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر ElementAtOrDefualt

عملگر ElementAtOrDefualt نیز همچون عملگر ElementAt کار می‌کند؛ اما در صورت وارد کردن اندیسی بزرگتر از اندیس مجاز توالی، دیگر یک استثناء رخ نخواهد داد و یک مقدار پیش فرض، بر اساس نوع عناصر توالی باز گردانده می‌شود.
مثال :
Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 },
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 50}
};
Ingredient element = ingredients.ElementAtOrDefault(5);
Console.WriteLine(element==null);
خروجی مثال بالا:
 True

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.


عملگر DefaultIfEmpty
عملگر DefaultIfEmpty یک توالی را دریافت کرده و به دو شکل عمل می‌کند:
1- اگر توالی شامل حداقل یک عنصر باشد، این توالی بدون هیچ تغییری به خروجی ارسال می‌شود.
2- اگر توالی هیچ عنصری نداشته باشد، توالی خروجی خالی نخواهد بود. در این حالت توالی خروجی تنها یک عضو دارد و آن هم مقدار پیش فرضی بر اساس نوع توالی می‌باشد.
مثال :
Ingredient[] ingredients =
{
   new Ingredient { Name = "Sugar", Calories = 500 },
   new Ingredient {Name = "Egg", Calories = 100},
   new Ingredient {Name = "Milk", Calories = 50}
};

IEnumerable<Ingredient> query = ingredients.DefaultIfEmpty();
foreach (Ingredient item in query)
{
  Console.WriteLine(item.Name);
}
خروجی مثال بالا :
Sugar
Egg
Milk
همانطور که می‌بینید توالی خروجی دقیقا شبیه توالی ورودی می‌باشد.
کد زیر حالت دوم معرفی شده‌ی در تعریف DefaultIfEmpty را نشان می‌دهد.
Ingredient[] ingredients = { };
IEnumerable<Ingredient> query = ingredients.DefaultIfEmpty();
foreach (Ingredient item in query)
{
   Console.WriteLine(item == null);
}
خروجی کد بالا :
 True

پیاده سازی توسط عبارت‌های جستجو


معادل این عملگر، کلمه‌ی کلیدی جدیدی در عبارت‌های جستجو وجود ندارد و ترکیب دو روش می‌تواند خروجی دلخواه را تولید کند.
مطالب
ارتقاء به Angular 6: بررسی تغییرات Angular CLI
اولین مرحله‌ی ارتقاء به Angular 6، به روز رسانی Angular CLI 1.x به نگارش 6 آن است. این شماره نگارش نیز با شماره نگارش Angular یکی شده‌است و دیگر 1x نیست. CLI 6.0 فقط پروژه‌های Angular 5.x و 6x را پشتیبانی می‌کند و برای نصب آن نیاز به حداقل NodeJS 8.9 و NPM 5.5 را خواهید داشت. بنابراین ابتدا دستورات زیر را صادر کرده و اگر هنوز از نگارش‌های قدیمی این ابزارها استفاده می‌کنید، قبل از هر کاری باید آن‌ها را به روز رسانی کنید:
node -v
npm -v
این نگارش از CLI در پشت صحنه از Webpack 4 استفاده می‌کند که نسبت به نگارش‌های پیشین آن بسیار سریعتر است، tree-shaking بهتری را انجام می‌دهد و در نهایت سبب تولید برنامه‌هایی با حجم کمتر و با سرعت build بیشتری خواهد شد.


فایل پیشین angular-cli.json حذف و فایل جدید angular.json بجای آن معرفی شده‌است

یکی از مهم‌ترین تغییرات CLI 6.0 نسبت به نگارش‌های قبلی آن، پشتیبانی از چندین پروژه است و به همین منظور ساختار فایل تنظیمات آن‌را به طور کامل تغییر داده‌اند و اگر دستور ng new project1 را صادر کنید، دیگر از فایل پیشین angular-cli.json خبری نبوده و بجای آن فایل جدید angular.json قابل مشاهده‌است:
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "project1": {
در اینجا ساختار ابتدای فایل angular.json را مشاهده می‌کنید که در آن مفهوم projects (و یا workspace در اینجا) به همراه project1 جدیدی که ایجاد کردیم، به عنوان زیر مجموعه‌ی آن قابل مشاهده‌است.
مزیت مهم این قابلیت، امکان ایجاد libraries است که به صورت توکار از این نگارش پشتیبانی می‌شود و می‌توان اجزایی مانند components ،directives ،pipes و services اشتراکی را در یک یا چندین کتابخانه قرار داد و سپس از آن‌ها در پروژه‌ی اصلی و یا چندین پروژه‌ی متصل استفاده کرد.
نگارش 6 در پشت صحنه، پروژه‌ی موفق ng-packagr را به مجموعه‌ی CLI اضافه کرده‌است و از این پس توسط خود CLI می‌توان کتابخانه‌های استاندارد Angular را تولید کرد. این مورد، مزیت استاندارد سازی کتابخانه‌های npm حاصل را نیز به همراه دارد؛ مشکلی که گاهی از اوقات به علت عدم رعایت این ساختار، با بسته‌های فعلی npm مخصوص Angular وجود دارند. برای مثال بدون استفاده‌ی از این ابزار، نیاز است مستندات 13 صفحه‌ای ساخت کتابخانه‌های Angular را سطر به سطر پیاده سازی کنید که توسط CLI 6.0، به صورت خودکار ایجاد و مدیریت می‌شود.

بنابراین اکنون سؤال مهمی که مطرح می‌شود این است: آیا باید فایل angular-cli.json پیشین را به صورت دستی به این فایل جدید به روز رسانی کرد و چگونه؟


به روز رسانی تمام بسته‌های سراسری سیستم

در ادامه پیش از هر کاری نیاز است تمام بسته‌های سراسری npm ایی را که هر از چندگاهی به سیستم خود اضافه کرده‌اید، به روز رسانی کنید. برای مشاهده‌ی لیست موارد تاریخ مصرف گذشته‌ی آن‌ها، دستور زیر را صادر کنید:
 npm outdated -g --depth=0
و برای به روز رسانی یکجای آن‌ها نیاز است دستور زیر اجرا شود:
 npm update -g


به روز رسانی خودکار ساختار فایل angular-cli.json

این به روز رسانی توسط CLI 6.0 به صورت خودکار پشتیبانی می‌شود و شامل این مراحل است:
ابتدا نیاز است بسته‌ی سراسری آن‌را به روز رسانی کرد:
 npm i -g @angular/cli
سپس وارد پوشه‌ی اصلی پروژه‌ی خود شده و این دستور را به صورت محلی نیز وارد کنید:
 npm install --save-dev @angular/cli@latest
با اینکار بسته‌ی CLI محلی پروژه به روز شده و اکنون می‌توانیم از قابلیت جدید آن که ng update نام دارد، استفاده کنیم. برای این منظور دستورات ذیل را به ترتیب اجرا کنید:
ng update @angular/cli
ng update @angular/core
ng update rxjs
دستور اول کار تبدیل خودکار فایل angular-cli.json قدیمی را به ساختار جدید آن انجام میدهد؛ با این لاگ:
DELETE .angular-cli.json
CREATE angular.json (4273 bytes)
UPDATE karma.conf.js (1008 bytes)
UPDATE src/tsconfig.spec.json (322 bytes)
UPDATE package.json (2076 bytes)
UPDATE tslint.json (3217 bytes)
دستور دوم بسته‌های هسته‌ی angular را به روز رسانی می‌کند و دستور سوم کار به روز رسانی کتابخانه‌ی rxjs را انجام می‌دهد.
لیست سایر بسته‌هایی را که می‌توان توسط این دستور به روز رسانی کرد، با اجرا دستور ng update می‌توانید مشاهده کنید. برای مثال اگر از Angular Material نیز استفاده می‌کنید، دستور به روز رسانی آن به صورت زیر است:
 ng update @angular/material


مشکل! دستور ng update کار نمی‌کند!

اگر پروژه‌ی شما صرفا مبتنی بر بسته‌های اصلی Angular باشد، مراحل یاد شده‌ی فوق را با موفقیت به پایان خواهید رساند. اما اگر از کتابخانه‌های ثالثی استفاده کرده باشید، منهای دستور «ng update @angular/cli» که کار تولید فایل جدید angular.json را انجام می‌دهد، مابقی با خطاهایی مانند «incompatible peer dependency» و یا «Invalid range:>=2.3.1 <3.0.0||>=4.0.0» متوقف می‌شوند.
در یک چنین حالتی نیاز است ابتدا وابستگی‌های محلی پروژه را به روز کرد و سپس دستورات ng update را تکرار نمود. برای این منظور ابتدا بسته‌ی npm-check-updates را نصب کنید:
 npm install npm-check-updates -g
کار آن به روز رسانی خودکار بسته‌های npm یک پروژه است. پس از آن دستورات زیر را صادر نمائید:
ncu -u
npm install
دستور اول تمام شماره نگارش‌های بسته‌های موجود در فایل package.json را به صورت خودکار به آخرین نگارش آن‌ها روز رسانی می‌کند و دستور دوم این بسته‌های جدید را دریافت و نصب خواهد کرد.
اکنون تمام وابستگی‌های محلی پروژه‌ی شما به صورت خودکار به آخرین نگارش آن‌ها به روز رسانی شده‌اند و اینبار اگر دستورات ذیل را اجرا کنید، با خطاهای یاد شده مواجه نخواهید شد:
ng update @angular/core
ng update rxjs

البته اگر در این حالت برنامه را کامپایل کنید، کار نخواهد کرد. علت اصلی آن به به‌روز رسانی rxjs به نگارش 6 آن مرتبط می‌شود که در مطلب بعدی پیگیری خواهد شد و این نگارش شامل حذفیات بسیاری است در جهت کاهش حجم آن، یکپارچکی و یک دست شدن syntax آن و همچنین بهبود قابل ملاحظه‌ی کارآیی آن. البته پیشنیاز الزامی آن آشنایی با pipe-able operators است. علت دیگر کامپایل نشدن برنامه هم می‌تواند عدم استفاده از HttpClient نگارش 4.3 به بعد باشد.


خاموش کردن اخطار «TypeScript version mismatch»

اگر نگارش TypeScript نصب شده‌ی در سیستم به صورت سراسری، با نگارش محلی پروژه‌ی شما یکی نباشد، اخطار «TypeScript version mismatch» را دریافت می‌کنید. روش خاموش کردن آن در CLI جدید با اجرای دستور زیر است:
 ng config cli.warnings.typescriptMismatch false
البته نگارش 6 نیاز به TypeScript 2.7.2 ذکر شده‌ی در package.json پروژه‌ی محلی را دارد؛ وگرنه اصلا شروع به کامپایل برنامه نمی‌کند:
{
  "devDependencies": {
    "typescript": "~2.7.2"
  }
}
بهترین راه برای یافتن این شماره، اجرای دستور ng new projet1 در یک پوشه‌ی خالی است و سپس مقایسه‌ی محتوای فایل package.json آن با فایل پروژه‌ی موجود.


 تغییرات ng build در نگارش 6

در نگارش 6، مفهوم پیشین environments به configurations تغییر یافته‌است و اینبار در فایل جدید angular.json تنظیم می‌شوند:
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-template-driven-forms-lab": {
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            }
          }
        },
و پیشتر اگر برای تنظیم محیط build از سوئیچ env استفاده می‌شد:
 ng build --env staging
اکنون این سوئیچ به configuration تغییر یافته‌است و نام آن از مداخل configurations فایل angular.json، مانند مثال فوق که «production» نام دارد، باید دریافت و تنظیم شود:
 ng build --configuration staging
و یا برای مثال دستور «ng build --env=prod» دیگر اجرا نمی‌شود و env=prod حذف شده‌است و اکنون اجرای  ng build --prod مانند اجرای دستور ng build --configuration=prod است.


تغییرات نام‌های نهایی تولیدی

در CLI 6.0، نام‌های نهایی تولیدی دیگر به همراه bundle  و یا chunk نیستند. برای مثال دستور ng build یک چنین خروجی را تولید می‌کند:
 >ng build --watch

Date: 2018-05-05T09:10:50.158Z
Hash: a43eab94ff01539b8592
Time: 31733ms
chunk {main} main.js, main.js.map (main) 9.38 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 226 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 5.4 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 15.6 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.05 MB [initial] [rendered]

و هش‌های حالت prod به صورت زیر تولید و به نام فایل اضافه می‌شوند:
>ng build --prod --watch

Date: 2018-05-05T09:17:01.803Z
Hash: f25fd6788a4969c52b70
Time: 73279ms
chunk {0} runtime.6afe30102d8fe7337431.js (runtime) 1.05 kB [entry] [rendered]
chunk {1} styles.34c57ab7888ec1573f9c.css (styles) 0 bytes [initial] [rendered]
chunk {2} polyfills.6c08419970f9e4781b69.js (polyfills) 59.4 kB [initial] [rendered]


ساده شدن افزودن وابستگی‌های ثالث به پروژه‌های CLI

برای نصب یک کتابخانه‌ی ثالث، پیشتر می‌بایستی ابتدا بسته‌ی npm آن جداگانه نصب و سپس فایل config برنامه، جهت معرفی مداخل آن، ویرایش می‌شد. اکنون دستور جدید ng add تمام این مراحل را به صورت خودکار انجام می‌دهد:
 ng add @angular/material
برای نمونه دستور فوق نه تنها فایل‌های Angular Material را دریافت می‌کند، بلکه فایل‌های CSS و ماژول‌های مرتبط با آن‌را نیز import خواهد کرد. البته این مورد از کلید ng-add فایل package.json بسته‌ی در حال نصب دریافت و تنظیم می‌شود و کتابخانه‌های جدید باید خود را بر این اساس وفق دهند.