استفاده از Awesomium.NET در برنامههای وب
ارتقاء OmniSharp به NET 6.0.
سایت sqlizer
کتابخانه angular-scroll-animate
An Angular.js directive which allows you to perform any javascript actions (in the controller, or on the element) when an element is scrolled into or out of, the users viewport, without requiring any other dependencies. Demo
نصب ابتدایی آن بسیار ساده است و نکته خاصی ندارد.
پس از نصب، یکبار 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
به روز رسانی نهایی
به روز شدهی این پروژه را بر اساس آخرین وابستگیهای آن از اینجا دریافت کنید.
CoffeeScript #14
قسمتهای اصلاح نشده
CoffeeScript در حال رفع برخی از معایب طراحی جاوااسکریپت است و این راه، بس طولانی است. همانطور که قبلا گفته شد، CoffeeScript به شدت به تجزیه و تحلیل استاتیک در زمان طراحی محدود شده است و هیچ بررسی در زمان اجرایی را برای بهبود کارآیی آن انجام نمیدهد.CoffeeScript از یک کامپایلر مستقیم منبع به منبع استفاده میکند. با این دیدگاه که هر دستور در CoffeeScript در نتیجه به یک دستور معادل در جاوااسکریپت تبدیل میشود.
CoffeeScript برای همهی کلمات کلیدی جاوااسکریپت، کلمهی معادلی ایجاد نمیکند، مانند typeof؛ و همچنین برخی از معایب طراحی جاوااسکریپت، به CoffeeScript نیز اعمال میشود.
در دو قسمت قبل + و + بر روی معایب طراحی در جاوااسکریپت که توسط CoffeeScript اصلاح شده بود، توضیح دادیم. حال میخواهیم درباره برخی از معایب جاوااسکریپت که CoffeeScript تا به حال نتوانسته است آنها را اصلاح کند صحبت کنیم.
استفاده از eval
در حالیکه CoffeeScript برخی از نقاط ضعف جاوااسکریپت را اصلاح کرده است، اما همچنان معایب دیگری نیز وجود دارند، که شما تنها باید از این نقاط ضعف آگاه باشید. یکی از این موارد، تابع eval است. برای استفاده از آن، باید با اشکالاتی که در حین کار با آن مواجه میشوید، آگاهی کامل داشته باشید و در صورت امکان از استفاده از آن اجتناب کنید.
تابع eval یک رشته از کد جاوااسکریپت را در حوزهی محلی اجرا میکند و توابعی مانند setTimeout و setInterval نیز میتوانند در آرگومان اولشان یک رشته از کد جاوااسکریپت را دریافت و ارزیابی کنند.
با این حال، مانند eval ،with نیز ردیابی کامپایلر را از کار میاندازد و این امر تاثیر بسیار زیادی بر روی کارآیی آن دارد. کامپایلر هیچ ایده ای درباره کدی که درون eval قرار داده شده است، ندارد تا زمانی که آن را اجرا کند. به همین دلیل نمیتواند هیچ عمل بهینه سازی را بر روی انجام دهد. یکی دیگر از نگرانیهای استفادهی از eval، امنیت است. در صورتیکه شما ورودی را به eval ارسال کنید، eval باعث میشود که کد شما به راحتی در معرض حملات تزریق کد قرار میگیرد. در 99% از مواقع، وقتی شما میخواهید از eval استفاده کنید، راههای بهتر و امنتری وجود دارند ( مانند استفاده از براکت ).
# Don't do this model = eval(modelName) # Use square brackets instead model = window[modelName]
استفاده از typeof
اپراتور typeof احتمالا بزرگترین نقص طراحی جاوااسکریپت است؛ تنها به این دلیل که اساسا به طور کامل شکست خورده است. در واقع از آن فقط یک استفاده میشود تا تشخیص داده شود که یک مقدار undefined است یا نه.
typeof undefinedVar is "undefined"
در اینجا لیستی از مشکلات، هنگام استفاده از typeof را مشاهده میکنید:
Value Class Type ---------------------------------------------- "foo" String string new String("foo") String object 1.2 Number number new Number(1.2) Number object true Boolean boolean new Boolean(true) Boolean object new Date() Date object new Error() Error object [1,2,3] Array object new Array(1, 2, 3) Array object new Function("") Function function /abc/g RegExp object new RegExp("meow") RegExp object {} Object object new Object() Object object
سوالی که اینجا مطرح میشود این است که ما چطور میتوانیم یک نوع را در جاوااسکریپت چک کنیم؟
خوب، خوشبختانه ()Object.prototype.toString ما را نجات داده است. اگر ما این تابع را بر روی یک شیء خاص فراخوانی کنیم، مقدار صحیح را بر میگرداند.
در اینجا مثالی از نحوهی پیاده سازی jQuery.type را مشاهده میکنید:
type = do -> classToType = {} for name in "Boolean Number String Function Array Date RegExp Undefined Null".split(" ") classToType["[object " + name + "]"] = name.toLowerCase() (obj) -> strType = Object::toString.call(obj) classToType[strType] or "object" # Returns the sort of types we'd expect: type("") # "string" type(new String) # "string" type([]) # "array" type(/\d/) # "regexp" type(new Date) # "date" type(true) # "boolean" type(null) # "null" type({}) # "object"
if typeof aVar isnt "undefined" objectType = type(aVar)
objectType = type(aVar?)
anArray?.push? aValue
استفاده از instanceof
کلمهی کلیدی instanceof نیز تقریبا همانند typeof شکست خورده است. در حالت ایده آل، instanceof، سازندهی دو شیء را با هم مقایسه میکند، در صورتیکه یک شیء نمونهای از شیء دیگر باشد، یک مقدار boolean را باز میگرداند. در واقع instanceof موقعی کار مقایسه را انجام میدهد که اشیاء، سفارشی سازی شده باشند. وقتی عمل مقایسه میخواهد بر روی این نوع اشیاء سفارشی سازی شده، انجام شود، استفاده از typeof بیفایده است.
new String("foo") instanceof String # true "foo" instanceof String # false
class Parent class Child extends Parent child = new Child child instanceof Child # true child instanceof Parent # true
استفاده از delete
از کلمه کلیدی delete برای حذف خصوصیات موجود در اشیاء به صورت کاملا مطمئن، میتوان استفاده کرد.anObject = {one: 1, two: 2} delete anObject.one anObject.hasOwnProperty("one") # false
aVar = 1 delete aVar typeof Var # "integer"
aVar = 1 aVar = null
{ "Logging": { "LogLevel": { "Default": "Warning" } } }
- Success
- Error
- Warning
- Verbose
- Debug
- Information
cmdlet | Name | Id |
Write-Output | Success | 1 |
Write-Error | Error | 2 |
Write-Warning | Warning | 3 |
Write-Verbose | Verbose | 4 |
Write-Debug | Debug | 5 |
Write-Information | Information | 6 |
به جز دو مورد اول، بقیه cmdletها خروجی را به صورت پیشفرض درون کنسول نمایش نمیدهند. به عنوان مثال اسکریپت زیر را در نظر بگیرید:
Write-Output 'Output' Write-Error 'This is an error' Write-Warning 'This is a warning' Write-Verbose 'This is verbose' Write-Debug 'This is Debug' Write-Information 'This is information'
با اجرای اسکریپت فوق خروجی زیر را خواهیم داشت:
Output Write-Error: This is an error WARNING: This is a warning
همانطور که مشاهده میکنید سه cmdlet فوق، خروجی را درون کنسول نمایش ندادهاند. این رفتار توسط مفهومی تحت عنوان Action Preference قابل تنظیم است که در واقع یک Enum است با مقدار زیر:
6 | Break | |
رخداد به صورت عادی مدیریت شده و برنامه ادامه پیدا میکند | 2 | Continue |
به طور کلی از رخداد صرفنظر خواهد شد؛ بدون اینکه چیزی در استریم نمایش داده شود | 4 | Ignore |
سوال پرسیده خواهد شد که برنامه را ادامه دهد یا متوقف کند | 3 | Inquire |
به طور کلی از رخداد صرفنظر خواهد شد | 0 | SilentlyContinue |
دستور را متوقف خواهد کرد | 1 | Stop |
دستور به نوعی معلق خواهد شد | 5 | Suspend |
بنابراین با تغییر Action Preference برای هر کدام از cmdletها میتوانیم رفتار اسکریپت قبلی را تغییر دهیم:
Write-Output 'Output' Write-Error 'This is an error' Write-Warning 'This is a warning' $VerbosePreference = 'Continue' Write-Verbose 'This is verbose' $DebugPreference = 'Continue' Write-Debug 'This is Debug' $InformationPreference = 'Continue' Write-Information 'This is information'
اکنون اگر اسکریپت فوق را اجرا کنید، سه خروجی آخر را نیز مشاهده خواهید کرد:
Output Write-Error: This is an error WARNING: This is a warning VERBOSE: This is verbose DEBUG: This is Debug This is information
هر کدام از استریمهای فوق قابل redirect شدن نیز هستند؛ برای اینکار میتوانیم از redirect operatorهایی که در PowerShell پشتیبانی میشود استفاده کنیم:
> >> >&1
به عنوان مثال میتوانیم تمام خطاها یا هشدارهای درون یک اسکریپت را به یک فایل منتقل کنیم:
./script.ps1 2>&1 > .\logs.txt
یا میتوانیم تمام Success streamها را به یک فایل هدایت کنیم:
.\script.ps1 > script.log
ارسال تمام Success, Warning, Errorها به یک فایل:
&{ Write-Warning "hello" Write-Error "hello" Write-Output "hi" } 3>&1 2>&1 > C:\Temp\redirection.log
ارسال تمام استریمها به یک فایل:
.\script.ps1 *> script.log
همچنین میتوانیم استریمی را به اصطلاح suppress کنیم که در خروجی نمایش داده نشود:
./script.ps1 1> $null 2> $null ./script.ps1 *> $null
از تکنیک فوق برای drop کردن خروجیهایی که نمیخواهیم نمایش داده شوند، استفاده میشود. در کد فوق دو Idهای ۱ و ۲ را به متغیر ویژهی null هدایت کردهایم؛ همچنین میتوانستیم از یک رشتهی خالی نیز بجای null استفاده کنیم. در خط بعدی از * استفاده کردهایم که به معنای تمامی استریمهای موجود است؛ با اینکار چیزی در خروجی نمایش داده نخواهد شد. یک روش دیگر برای drop کردن، استفاده از دستور Out-Null است:
Get-ChildItem | Out-Null
لازم به ذکر است که این cmdlet تا قبل از نسخه ۶ خیلی کند بود؛ زیرا همانند دیگر cmdletهای درون pipeline میبایست یک ورودی (InputObject) را دریافت کند که باعث میشد هزینهی پردازشی بالایی داشته باشد. اما در نسخه ۶ به بعد این مشکل رفع شدهاست و پارزر به محض رسیدن به این keyword به صورت کلی خروجی را discard میکند بدون اینکه Out-Null را فراخوانی کند؛ در واقع این cmdlet یک hint برای پارزر است. روش دیگر برای drop کردن خروجی، انتساب نتیجه یک دستور به متغییر null است:
New-Item -Type Directory -Path $path | Out-Null $null = New-Item -Type Directory -Path $path
همچنین میتوانیم خروجی یک دستور را به void تبدیل کنیم؛ که نتیجه مشابه با تکنیکهای فوق دارد:
[void](New-Item -Name test -ItemType Directory)
یک نکته در مورد Out-Null
در loopهای بزرگ ممکن است Out-Null حتی در PowerShell 7.x هم کند عمل کند:
PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $i | Out-Null } } | Select-Object TotalSeconds TotalSeconds ------------ 4.3056315 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $null = $i } } | Select-Object TotalSeconds TotalSeconds ------------ 1.1210884 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { [void]$i } } | Select-Object TotalSeconds TotalSeconds ------------ 1.130507 PS > Measure-Command { for($i=0; $i -lt 1mb; $i++) { $i > $null } } | Select-Object TotalSeconds TotalSeconds ------------ 1.3832427