امکانات ASP.NET Core 2.0
مقدمه ای بر asp.net core 2.0
مهاجرت به کنترل های AngularJs 2.0
WinJS سورس باز شد
OpenCVSharp #7
اینترفیس یا API زبان C کتابخانهی OpenCV مربوط است به نگارشهای 1x این کتابخانه و تمام مثالهایی را که تاکنون ملاحظه کردید، بر مبنای همین اینترفیس تهیه شده بودند. اما از OpenCV سری 2x، این اینترفیس صرفا جهت سازگاری با نگارشهای قبلی، نگهداری میشود و اینترفیس اصلی مورد استفاده، API جدید ++C آن است. به همین جهت کتابخانهی OpenCVSharp نیز در فضای نام OpenCvSharp.CPlusPlus و توسط اسمبلی OpenCvSharp.CPlusPlus.dll، امکان دسترسی به این API جدید را فراهم کردهاست که در ادامه نکات مهم آنرا بررسی خواهیم کرد.
تبدیل مثالهای اینترفیس C به اینترفیس ++C
مثال «تبدیل تصویر به حالت سیاه و سفید» قسمت سوم را درنظر بگیرید. این مثال به کمک اینترفیس C کتابخانهی OpenCV کار میکند. معادل تبدیل شدهی آن به اینترفیس ++C به صورت ذیل است:
// Cv2.ImRead using (var src = new Mat(@"..\..\Images\Penguin.Png", LoadMode.AnyDepth | LoadMode.AnyColor)) using (var dst = new Mat()) { Cv2.CvtColor(src, dst, ColorConversion.BgrToGray); // How to export using (var bitmap = dst.ToBitmap()) // => OpenCvSharp.Extensions.BitmapConverter.ToBitmap(dst) { bitmap.Save("gray.png", ImageFormat.Png); } using (new Window("BgrToGray C++: src", image: src)) using (new Window("BgrToGray C++: dst", image: dst)) { Cv2.WaitKey(); } }
- بجای IplImage، از کلاس Mat استفاده شدهاست.
- برای ایجاد Clone یک تصویر نیازی نیست تا پارامترهای خاصی را به Mat دوم (همان dst) انتساب داد و ایجاد یک Mat خالی کفایت میکند.
- اینبار بجای کلاس Cv اینترفیس C، از کلاس Cv2 اینترفیس ++C استفاده شدهاست.
- متد الحاقی ToBitmap نیز که در کلاس OpenCvSharp.Extensions.BitmapConverter قرار دارد، با نمونهی Mat سازگار است و به این ترتیب میتوان خروجی معادل دات نتی Mat را با فرمت Bitmap تهیه کرد.
- بجای CvWindow، در اینجا باید از Window سازگار با Mat، استفاده شود.
- new Mat معادل Cv2.ImRead است. بنابراین اگر مثال ++C ایی را در اینترنت یافتید:
cv::Mat src = cv::imread ("foo.jpg"); cv::Mat dst; cv::cvtColor (src, dst, CV_BGR2GRAY);
کار مستقیم با نقاط در OpenCVSharp
متدهای ماتریسی OpenCV، فوق العاده در جهت سریع اجرا شدن و استفادهی از امکانات سخت افزاری و پردازشهای موازی، بهینه سازی شدهاند. اما اگر قصد داشتید این متدهای سریع را با نمونههایی متداول و نه چندان سریع جایگزین کنید، میتوان مستقیما با نقاط تصویر نیز کار کرد. در ادامه قصد داریم کار فیلتر توکار Not را که عملیات معکوس سازی رنگ نقاط را انجام میدهد، شبیه سازی کنیم.
در اینجا نحوهی دسترسی مستقیم به نقاط تصویر بارگذاری شده را توسط اینترفیس C، ملاحظه میکنید:
using (var src = new IplImage(@"..\..\Images\Penguin.Png", LoadMode.AnyDepth | LoadMode.AnyColor)) using (var dst = new IplImage(src.Size, src.Depth, src.NChannels)) { for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { CvColor pixel = src[y, x]; dst[y, x] = new CvColor { B = (byte)(255 - pixel.B), G = (byte)(255 - pixel.G), R = (byte)(255 - pixel.R) }; } } // [C] Accessing Pixel // https://github.com/shimat/opencvsharp/wiki/%5BC%5D-Accessing-Pixel using (new CvWindow("C Interface: Src", image: src)) using (new CvWindow("C Interface: Dst", image: dst)) { Cv.WaitKey(0); } }
روش ارائه شدهی در اینجا یکی از روشهای دسترسی به نقاط، توسط اینترفیس C است. سایر روشهای ممکن را در Wiki آن میتوانید مطالعه کنید.
شبیه به همین کار را میتوان به نحو ذیل توسط اینترفیس ++C کتابخانهی OpenCVSharp نیز انجام داد:
// Cv2.ImRead using (var src = new Mat(@"..\..\Images\Penguin.Png", LoadMode.AnyDepth | LoadMode.AnyColor)) using (var dst = new Mat()) { src.CopyTo(dst); for (var y = 0; y < src.Height; y++) { for (var x = 0; x < src.Width; x++) { var pixel = src.Get<Vec3b>(y, x); var newPixel = new Vec3b { Item0 = (byte)(255 - pixel.Item0), // B Item1 = (byte)(255 - pixel.Item1), // G Item2 = (byte)(255 - pixel.Item2) // R }; dst.Set(y, x, newPixel); } } // [Cpp] Accessing Pixel // https://github.com/shimat/opencvsharp/wiki/%5BCpp%5D-Accessing-Pixel //Cv2.NamedWindow(); //Cv2.ImShow(); using (new Window("C++ Interface: Src", image: src)) using (new Window("C++ Interface: Dst", image: dst)) { Cv2.WaitKey(0); } }
میتوانید سایر روشهای دسترسی به نقاط را توسط اینترفیس ++C، در Wiki این کتابخانه مطالعه نمائید.
کدهای کامل این مثال را از اینجا میتوانید دریافت کنید.
public class AuditableEntitiesInterceptor : SaveChangesInterceptor { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ILogger<AuditableEntitiesInterceptor> _logger; public AuditableEntitiesInterceptor( IHttpContextAccessor httpContextAccessor, ILogger<AuditableEntitiesInterceptor> logger) { _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public override InterceptionResult<int> SavingChanges( DbContextEventData eventData, InterceptionResult<int> result) { if (eventData == null) { throw new ArgumentNullException(nameof(eventData)); } BeforeSaveTriggers(eventData.Context); return result; } public override ValueTask<InterceptionResult<int>> SavingChangesAsync( DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default) { if (eventData == null) { throw new ArgumentNullException(nameof(eventData)); } BeforeSaveTriggers(eventData.Context); return ValueTask.FromResult(result); } private void BeforeSaveTriggers(DbContext? context) { // ValidateEntities(context); // ApplyAudits(context?.ChangeTracker); } }
services.AddSingleton<AuditableEntitiesInterceptor>();
services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) => optionsBuilder .UseSqlServer(connectionString) .AddInterceptors(serviceProvider.GetRequiredService<AuditableEntitiesInterceptor>()));
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
public class LockFilter : ActionFilterAttribute { static ConcurrentDictionary<StringBuilder, int> _properties; static LockFilter() { _properties = new ConcurrentDictionary<StringBuilder, int>(); } public int Duration { get; set; } public string VaryByParam { get; set; } public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var actionArguments = context.ActionArguments.Values.Single(); var properties = VaryByParam.Split(",").ToList(); StringBuilder key = new StringBuilder(); foreach (var actionArgument in actionArguments.GetType().GetProperties()) { if (!properties.Any(t => t.Trim().ToLower() == actionArgument.Name.ToLower())) continue; var value = actionArguments.GetType().GetProperty(actionArgument.Name).GetValue(actionArguments, null).ToString(); key.Append(value); } _properties.AddOrUpdate(key, 1, (x, y) => y + 1); // rest of code } }