Integrated Terminal improvements - Find support, select/copy multiple pages.
Command Palette MRU list - Quickly find and run your recently used commands.
New Tasks menu - Top-level Tasks menu for running builds and configuring the task runner.
Automatic indentation - Auto indent while typing, moving, and pasting source code.
Emmet abbreviation enhancements - Add Emmet to any language. Multi-cursor support.
New Diff review pane - Navigate Diff editor changes quickly with F7, displayed in patch format.
Angular debugging recipe - Debug your Angular client in VS Code.
Better screen reader support - Aria properties to better present list and drop-down items.
Preview: 64 bit Windows build - Try out the Windows 64 bit version (Insiders build).
Preview: Multi-root workspaces - Open multiple projects in the same editor (Insiders build).
نگاهی به آینده WebAssembly
The future of WebAssembly - A look at upcoming features and proposals
WebAssembly is a performance optimised virtual machine that was shipped in all four major browsers earlier this year. It is a nascent technology and the current version is very much an MVP (minimum viable product). This blog post takes a look at the WebAssembly roadmap and the features it might be gain in the near future.
I’ll try to keep this blog post relatively high-level, so I’ll skip over some of the more technical proposals, instead focusing on what they might mean for languages that target WebAssembly.
نصب ابتدایی آن بسیار ساده است و نکته خاصی ندارد.
پس از نصب، یکبار VS.NET را بسته و سپس باز کنید. این قالب جدید، ذیل قسمت پروژههای ویندوز مرتبط با ویژوال سی شارپ، ظاهر خواهد شد:
در این حال اگر یک پروژه جدید را آغاز کنید، این قالب تدارک دیده شده، لایهها و قسمتهای مختلف را به صورت خودکار اضافه خواهد کرد:
نکته مهم! برنامه کامپایل نمیشود!
به عمد، جهت کاهش حجم قالب دریافتی فوق، فایلهای باینری آن پیوست نشدهاند. وگرنه باید بالای 30 مگابایت را دریافت میکردید که واقعا نیازی نیست.
اما اگر به هر پروژه داخل Solution دقت کنید، فایل متنی packages.config آن نیز پیوست شده است. به کمک این فایلها به سادگی میتوان تمام وابستگیها را از طریق NuGet بازیابی کرد.
برای این منظور ابتدا به اینترنت متصل شده (مهم) و سپس بر روی Solution کلیک راست کرده و گزینه فعال سازی Restore کلیه بستههای نیوگت را انتخاب کنید.
پس از اینکار، آخرین نگارش NuGet.exe از اینترنت دریافت و به پروژه اضافه میشود:
اکنون اگر Solution را Build کنید، اولین کاری که صورت خواهد گرفت، دریافت کلیه وابستگیها از سایت NuGet است. اندکی تامل کنید تا اینکار تمام شود.
پس از پایان کار دریافت، پوشه packages در کنار فایل sln پروژه ایجاد شده، تشکیل میشود.
یکبار وجود آنرا بررسی کنید.
اکنون اگر برنامه را Build کنید احتمالا پیغام میدهد که Fody را نمیتواند پیدا کند با اینکه دریافت شده و در پوشه packages موجود است. هر زمان، هر پیغام خطایی در مورد Fody مشاهده کردید، فقط یکبار VS.NET را بسته و باز کنید. مشکل حل میشود!
تنها کاری که پس از بازسازی پوشه packages بهتر است صورت گیرد (اختیاری است البته)، صدور دستور ذیل در خط فرمان پاور شل است:
PM> Update-Package
پس از اینکار، نیاز است یکبار VS.NET را بسته و مجددا باز کنید (مهم) تا تمام وابستگیها به درستی بارگذاری شوند. خصوصا بسته Fody که کار AOP را انجام میدهد. در غیر اینصورت موفق به Build پروژه نخواهید شد.
بنابراین به صورت خلاصه:
الف) یکبار گزینه فعال سازی Restore کلیه بستههای نیوگت را انتخاب کنید.
ب) پروژه را Build کنید تا وابستگیها را از سایت NuGet دریافت کند.
ج) دستور Update-Package را اجرا نمائید (اختیاری).
ج) VS.NET را پس از سه مرحله فوق، یکبار بسته و باز کنید.
در کل بستههای مورد استفاده به این شرح هستند:
PM> Install-Package MahApps.Metro -Pre PM> Install-Package MahApps.Metro.Resources PM> Install-Package EntityFramework PM> Install-Package structuremap PM> Install-Package PropertyChanged.Fody PM> Install-Package MvvmLight PM> Install-Package Microsoft.SqlServer.Compact
یک نکته جانبی
فید NuGet در VS.NET به Https تنظیم شده است. اگر دسترسی به Https برای شما به کندی صورت میگیرد فقط کافی است مسیر فید آنرا در منوی Tools، گزینهی Options، ذیل قسمت Package manager یافته و به http://nuget.org/api/v2 تغییر دهید؛ یعنی به Http خالی، بجای Https؛ تا سرعت دریافت بستههای NuGet مورد نظر افزایش یابند.
اجرای پروژه و برنامه
پس از این مراحل و Build موفقیت آمیز پروژه، برنامه را اجرا کنید. در اولین بار اجرای برنامه به صورت خودکار بانک اطلاعاتی به همراه ساختار جداول تشکیل میشوند. اما ... با خطای زیر مواجه خواهید شد:
The path is not valid. Check the directory for the database. [ Path = D:\...\bin\Debug\Db\db.sdf ]
<connectionStrings> <clear/> <add name="MyWpfFrameworkContext" connectionString="Data Source=|DataDirectory|\Db\db.sdf;Max Buffer Size=30720;File Mode=Read Write;" providerName="System.Data.SqlServerCE.4.0" /> </connectionStrings>
برای ورود به برنامه از نام کاربری Admin و کلمه عبور 123456 استفاده نمائید.
این کاربر پیش فرض در کلاس MyWpfFrameworkMigrations لایه دادههای برنامه، توسط متد addRolesAndAdmin اضافه شده است.
خوب! تا اینجا با نحوه نصب و راه اندازی این قالب جدید آشنا شدیم. در قسمتهای بعد، به جزئیات ارتباطات و نحوه استفاده از آن به عنوان پایه یک کار و پروژه جدید، خواهیم پرداخت.
به روز رسانی 1.1
جهت سازگاری با EF 6 ، StructureMap 3 و همچنین VS 2013، پروژه به روز شد: WpfFrmwork_1.1.zip
به روز رسانی نهایی
به روز شدهی این پروژه را بر اساس آخرین وابستگیهای آن از اینجا دریافت کنید.
Performance of your ASP.NET web application is important. There is a lot of evidence to suggest that slow loading times and clunky interaction, will drive customers elsewhere. Even in the case of internal applications where the users have no option but to use the application, their satisfaction is tightly coupled to speed.
There are a ton of ways to improve the performance of a website, let's look at fifteen of them.
اخلاق مشارکت در یک پروژهی سورس باز
بعضی از توسعه دهندهها در حین مشارکت در یک پروژهی سورس باز، برای مثال جهت افزودن قابلیتی جدید و یا رفع مشکلی، ابتدا سعی میکنند تا کدهای فعلی را برای خودشان «قابل فهمتر» کنند. این قابل فهمتر کردن پروژه، شامل تغییر نام متغیرها و متدهای فعلی، انتقال کدهای موجود به فایلهایی دیگر یا حتی یکی کردن چندین فایل با هم، مرتب سازی متدهای یک کلاس بر اساس حروف الفباء و امثال آن میشود.
این کارها را نباید در حین مشارکت و توسعهی پروژههای سورس باز دیگران انجام دهید! اگر هدفتان رفع مشکلی است یا افزودن قابلیتی جدید، باید نحوهی کدنویسی فعلی را حفظ کنید. از این جهت که نگهدارندهی اصلی پروژه، پیش از شما اینکار را شروع کردهاست و زمانیکه شما به پروژهای دیگر رجوع خواهید کرد، باز نیز باید همین کار را ادامه دهد.
اگر refactoring گستردهی شما به هر نحوی سبب بهبود پروژهی اصلی میشود، ابتدا این مورد را با مسئول اصلی پروژه مطرح کنید. اگر او قبول کرد، سپس اقدام به چنین کاری نمائید.
بحث در مورد تغییرات پیش از ارسال PR
قبل از اینکه PR ایی را ارسال کنید، بهتر است یک issue یا ticket جدید را باز کرده و در مورد آن بحث کنید یا توضیح دهید. در این حالت ممکن است توضیحات بهتری را در مورد سازگار سازی تغییرات خود با کدهای فعلی دریافت کنید.
Pull requestها را کوچک نگهدارید
برای اینکه شانس قبول شدن PR خود را بالا ببرید، حجم و تمرکز آنرا کوچک نگه دارید. بسیاری از توسعه دهندههای سورس باز اگر با یک PR حجیم روبرو شوند، آنرا رد میکنند چون مشکل اصلی، مدت زمان بالایی است که باید جهت بررسی این PR اختصاص داد. هرچقدر حجم آن بیشتر باشد، زمان بیشتری را خواهد برد.
فقط یک کار را انجام دهید
شبیه به اصل تک مسئولیتی کلاسها، یک PR نیز باید تنها یک کار را انجام دهد و بر روی یک موضوع خاص تمرکز داشته باشد. فرض کنید PR ایی را ارسال کردهاید که سه مشکل A، B و C را برطرف میکند. از دیدگاه مسئول اصلی پروژه، موارد A و C قابل قبول هستند؛ اما نه مورد C مطرح شده. در این حالت کل PR شما برگشت خواهد خورد. به همین جهت بهتر است بجای یک PR، سه PR مختلف و مجزا را جهت رفع مشکلات A، B و C ارسال کنید.
سازگاری تغییرات ارسالی را بررسی کنید
حداقل کاری را که پیش از ارسال PR باید انجام دهید این است که بررسی کنید آیا این تغییرات قابل Build هستند یا خیر. همچنین اگر پروژه دارای یک سری Unit tests است، حتما آنها را یکبار بررسی کنید تا مطمئن شوید جای دیگری را به هم نریختهاید. ضمنا وجود این تستها به صورت ضمنی به این معنا است که تغییرات جدید شما نیز باید به همراه تستهای مرتبطی باشند تا پذیرفته شوند.
PR ایی را بر روی شاخهی master ارسال نکنید
پس از اینکه یک fork از پروژهای سورس باز را ایجاد کردید و سپس آنرا clone نمودید تا به صورت Local بتوانید با آن کار کنید، فراموش نکنید که در همینجا باید یک branch و انشعاب جدید را جهت کار بر روی ویژگی مدنظر خود ایجاد کنید (برای مثال feature-X, fix-Y). بسیاری از پروژههای سورس باز به هیچ عنوان PRهای کار شدهی بر روی انشعاب master را قبول نمیکنند.
برای مطالعه بیشتر
Open Source Contribution Etiquette
ten tips for better Pull Requests
Getting a Pull Request Accepted
Optimize Your Pull-request
افزونهای برای نمایش ثوابت در کدها
- کلیک راست بر روی تصویر
- انتخاب چندین تصویر
- بهینهسازی تصاویر موجود در فایلهای CSS
ایجاد تصاویر Sprite
<?xml version="1.0" encoding="utf-8"?> <sprite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://vswebessentials.com/schemas/v1/sprite.xsd"> <settings> <!--Determines if the sprite image should be automatically optimized after creation/update.--> <optimize>true</optimize> <!--Determines the orientation of images to form this sprite. The value must be vertical or horizontal.--> <orientation>vertical</orientation> <!--File extension of sprite image.--> <outputType>png</outputType> <!--Determin whether to generate/re-generate this sprite on building the solution.--> <runOnBuild>false</runOnBuild> <!--Use full path to generate unique class or mixin name in CSS, LESS and SASS files. Consider disabling this if you want class names to be filename only.--> <fullPathForIdentifierName>true</fullPathForIdentifierName> <!--Use absolute path in the generated CSS-like files. By default, the URLs are relative to sprite image file (and the location of CSS, LESS and SCSS).--> <useAbsoluteUrl>false</useAbsoluteUrl> <!--Specifies a custom subfolder to save CSS files to. By default, compiled output will be placed in the same folder and nested under the original file.--> <outputDirectoryForCss /> <!--Specifies a custom subfolder to save LESS files to. By default, compiled output will be placed in the same folder and nested under the original file.--> <outputDirectoryForLess /> <!--Specifies a custom subfolder to save SCSS files to. By default, compiled output will be placed in the same folder and nested under the original file.--> <outputDirectoryForScss /> </settings> <!--The order of the <file> elements determines the order of the images in the sprite.--> <files> <file>/Content/Images/01.png</file> <file>/Content/Images/02.png</file> <file>/Content/Images/03.png</file> <file>/Content/Images/04.png</file> </files> </sprite>
/* This is an example of how to use the image sprite in your own CSS files */ .Content-Images-01 { /* You may have to set 'display: block' */ width: 32px; height: 32px; background: url('icons.png') 0 0; } .Content-Images-02 { /* You may have to set 'display: block' */ width: 32px; height: 32px; background: url('icons.png') 0 -32px; } .Content-Images-03 { /* You may have to set 'display: block' */ width: 32px; height: 32px; background: url('icons.png') 0 -64px; } .Content-Images-04 { /* You may have to set 'display: block' */ width: 32px; height: 32px; background: url('icons.png') 0 -96px; }
<div class="Content-Images-01"></div> <div class="Content-Images-02"></div> <div class="Content-Images-03"></div> <div class="Content-Images-04"></div>
<img src="https://www.dntips.ir/images/logo.png" />
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAAAA7ljmRAAAAGElEQVQIW2P4DwcMDAxAfBvMAhEQMYgcACEHG8ELxtbPAAAAAElFTkSuQmCC" />
<img src="data:image/png;base64,iVBOR..." />
Nebular is a great toolkit if you build Rich UI web-application based on Angular, and want to bootstrap your development using essential features out of the box. It provides you with a set of native Angular components, themeable components, authentication and security layers easily configurable for your API. At the same time, Nebular allows you to use it together with any other UI library you choose.
Please open an issue in the library repository to alert its author and ask them to package the library using the Angular Package Format (https://goo.gl/jB3GVv).
مراحل ایجاد یک پروژهی «کتابخانه» توسط Angular CLI 6.0
مرحلهی اول ایجاد یک پروژهی کتابخانه، مانند قبل، توسط دستور ng new و ایجاد یک پروژهی دلخواه جدید است:
ng new my-lib-test
پس از ایجاد پروژهی my-lib-test توسط دستور فوق و وارد شدن به پوشهی اصلی آن توسط خط فرمان، میتوان با اجرای دستور زیر، پروژههای دیگری را به پروژهی جاری افزود:
ng generate application my-app-name
ng generate library my-lib
همچنین یک پوشهی جدید به نام projects نیز ایجاد شده و پروژهی my-lib داخل آن قرار گرفتهاست.
فایل جدید public_api.ts
پس از ایجاد کتابخانهی جدید «my-lib»، فایل جدیدی به نام projects\my-lib\src\public_api.ts نیز به آن اضافه شدهاست:
با این محتوا:
/* * Public API Surface of my-lib */ export * from './lib/my-lib.service'; export * from './lib/my-lib.component'; export * from './lib/my-lib.module';
برای مثال اگر فایل جدید projects\my-lib\src\lib\my-lib.models.ts را به این کتابخانه اضافه کنیم که شامل تعدادی مدل و اینترفیس قابل دسترسی توسط استفاده کنندگان باشد، باید یک سطر زیر را به انتهای فایل public_api.ts اضافه کنیم:
export * from './lib/my-lib.models';
این پروژهی کتابخانه حتی به همراه فایلهای package.json, tsconfig.json, tslint.json مخصوص به خود نیز میباشد تا بتوان آنها را صرفا جهت این پروژه سفارشی سازی کرد.
ساختار my-lib.service پیشفرض یک پروژهی کتابخانه
اگر به فایل projects\my-lib\src\lib\my-lib.service.ts دقت کنیم:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class MyLibService { constructor() { } }
شاید بپرسید چرا؟ هدف اصلی از آن، بهبود فرآیند tree-shaking یا حذف کدهای مرده و استفاده نشدهاست. ممکن است سرویسی را تعریف کنید، اما در برنامه استفاده نشود. این حالت خصوصا در پروژههای کتابخانههای ثالث ممکن است زیاد رخ دهد. به همین جهت با ارائهی این قابلیت، امکان حذف سادهتر سرویسهایی که در برنامه استفاده نشدهاند از خروجی نهایی کامپایل شده، وجود خواهد داشت.
چگونه به پروژهی کتابخانهی جدید، یک کامپوننت جدید را اضافه کنیم؟
تمام دستورات Angular CLI، در اینجا نیز کار میکنند. تنها تفاوت آنها، ذکر صریح نام پروژهی مورد استفاده است:
ng generate component show-data --project=my-lib
البته در اینجا باید فایل my-lib.module.ts را اندکی ویرایش کرد و ShowDataComponent را به قسمت exports نیز افزود:
@NgModule({ imports: [ CommonModule, HttpClientModule ], declarations: [MyLibComponent, ShowDataComponent], exports: [MyLibComponent, ShowDataComponent] }) export class MyLibModule { }
همچنین قسمت imports آن نیز به صورت پیشفرض خالی است. اگر نیاز است با ngIf کار کنید، باید CommonModule را در اینجا قید کنید و اگر نیاز است تبادلات HTTP وجود داشته باشد، ذکر HttpClientModule نیز ضروری است.
مرحلهی ساخت پروژه
پیش از استفادهی از این پروژهی کتابخانه، باید آنرا build کرد:
ng build my-lib
پس از اجرای این دستور، خروجی ذیل مشاهده میشود:
Building Angular Package Building entry point 'my-lib' Rendering Stylesheets Rendering Templates Compiling TypeScript sources through ngc Downleveling ESM2015 sources through tsc Bundling to FESM2015 Bundling to FESM5 Bundling to UMD Minifying UMD bundle Remap source maps Relocating source maps Copying declaration files Writing package metadata Removing scripts section in package.json as it's considered a potential security vulnerability. Built my-lib Built Angular Package! - from: D:\my-lib-test\projects\my-lib - to: D:\my-lib-test\dist\my-lib
استفادهی از کتابخانهی تولید شده
پس از پایان موفقیت آمیز مرحلهی Build، اکنون نوبت به استفادهی از این کتابخانه است. استفادهی از آن نیز همانند تمام کتابخانهها و وابستگیهای ثالثی است که تا پیش از این از آنها استفاده کردهایم. برای مثال ماژول آنرا در قسمت imports مربوط به NgModule کلاس AppModule معرفی میکنیم. برای این منظور به فایل src\app\app.module.ts مراجعه کرده و MyLibModule را به نحو ذیل اضافه میکنیم:
import { MyLibModule } from "my-lib"; @NgModule({ imports: [ BrowserModule, MyLibModule ] }) export class AppModule { }
اما سؤال اینجا است که آیا این پوشه پس از build، داخل پوشهی node_modules نیز کپی شدهاست؟ پاسخ آن خیر است و برای مدیریت خودکار آن، به صورت زیر عمل شدهاست:
اگر به فایل tsconfig.json اصلی و واقع در ریشهی workspace دقت کنید، پس از اجرای دستور «ng generate library my-lib»، قسمت paths آن نیز به صورت خودکار ویرایش شدهاست:
{ "compilerOptions": { "paths": { "my-lib": [ "dist/my-lib" ] } } }
برای نمونه اگر شارهگر ماوس را بر روی my-lib قرار دهید، به درستی مسیر خوانده شدن آن، تشخیص داده میشود.
به این ترتیب مسیر این import، چه در این پروژهی محلی و چه برای کسانیکه پوشهی dist/my-lib را به صورت یک بستهی npm جدید دریافت کردهاند، یکی خواهد بود.
در ادامه اگر به فایل app.component.html مراجعه کرده و selector کامپوننت show-data را به آن اضافه کنیم:
<lib-show-data></lib-show-data>
توزیع کتابخانهی ایجاد شده برای عموم
برای اینکه این کتابخانهی تولیدی را در اختیار عموم، در سایت npm قرار دهیم، ابتدا باید کتابخانه را در حالت production build تولید و سپس آنرا publish کرد:
ng build my-lib --prod cd dist/my-lib npm publish
البته دستور آخر نیاز به ایجاد یک اکانت در سایت npm و وارد شدن به آنرا دارد. جزئیات بیشتر آن در اینجا.
معرفی پروژه NotifyPropertyWeaver
اگر به Wiki آن مراجعه نمائید، لیست افزونههای قابل توجهی را در مورد آن خواهید یافت که PropertyChanged تنها یکی از آنها است.
پیشنیازها
الف) صفحه پروژه در GitHub
ب) دریافت از طریق نوگت
روش استفاده
پس از نصب بسته نوگت پروژه PropertyChanged.Fody
PM> Install-Package PropertyChanged.Fody
using PropertyChanged; namespace AOP02 { [ImplementPropertyChanged] public class Person { public string Id { set; get; } public string Name { set; get; } } }
------ Build started: Project: AOP02, Configuration: Debug x86 ------ Fody (version 1.13.6.1) Executing Finished Fody 287ms. AOP02 -> D:\Prog\AOP02\bin\Debug\AOP02.exe ========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
using System; using System.ComponentModel; using System.Runtime.CompilerServices; namespace AOP02 { public class Person : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public string Id { [System.Runtime.CompilerServices.CompilerGenerated] get { return this.<Id>k__BackingField; } [System.Runtime.CompilerServices.CompilerGenerated] set { if (string.Equals(this.<Id>k__BackingField, value, System.StringComparison.Ordinal)) { return; } this.<Id>k__BackingField = value; this.OnPropertyChanged("Id"); } } public string Name { [System.Runtime.CompilerServices.CompilerGenerated] get { return this.<Name>k__BackingField; } [System.Runtime.CompilerServices.CompilerGenerated] set { if (string.Equals(this.<Name>k__BackingField, value, System.StringComparison.Ordinal)) { return; } this.<Name>k__BackingField = value; this.OnPropertyChanged("Name"); } } public virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler propertyChanged = this.PropertyChanged; if (propertyChanged != null) { propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } }