نظرات اشتراک‌ها
پایان کار Inoreader برای کاربران عادی
سلام
مورد مناسبی با دات نت پیاده سازی شده؟
از موارد غیر دات نتی موردی رو میشناسید که بدون دردسر بشه روی یک سرور ویندوزی راه انداخت؟
اشتراک‌ها
اجرای ورد پرس با کمک .net core

با کمک peachpie می‌توان پلی بین php و دات نت زد 

استفاده از کد app.UseWordPress()   در یک برنامه‌ی دات نتی در نوع خود جالب هست !

اجرای ورد پرس با کمک .net core
مطالب
لینک‌های هفته سوم دی

وبلاگ‌ها ، سایت‌ها و مقالات ایرانی (داخل و خارج از ایران)

ASP. Net

  • ویدیویی درباره‌ی ASP.Net 4 (بهبودهای حاصل شده در web forms از جهت کار با اسکریپت‌ها خصوصا با تاکید بر jQuery و همچنین ذکر اینکه با آمدن ASP.Net MVC ، وب فرم‌ها کهنه نشده‌ و همچنان توسعه و بهبود داده خواهند شد)، یا مقاله‌ای در این مورد

طراحی و توسعه وب

PHP

اس‌کیوال سرور

سی شارپ

عمومی دات نت

مسایل اجتماعی و انسانی برنامه نویسی

متفرقه

نظرات نظرسنجی‌ها
آیا با وجود سی‌ام‌اس فروشگاهی قدرتمندی مثل nopCommerce یا SmartStore آیا منطقی است که ما دوباره خودمان از صفر کد بزنیم؟
چند تا از نمونه هایی که عملا به صورت عمیق (درگیر شدن در کد‌های هسته و ماژول‌های آن و توسعه سیستم) با آنها کار کرده ایم:
برای PHP
  1. woocommerce (فروشگاه‌های تا متوسط و عملیات تجاری سبک) - سفارشی سازی در حد وردپرس - راحته ولی رو اعصابه
  2. prestashop (فروشگاه‌های تا متوسط و عملیات تجاری متوسط) - سفارشی سازی متوسط - زیرساخت‌های خیلی پیشرفته درش وجود ندارد
  3. magento (فروشگاه‌های تا سایز بزرگ و عملیات تجاری بزرگ) - سفارشی سازی پیشرفته 
برای .NET
  1. nopCommerce(فروشگاه‌های تا متوسط و عملیات تجاری متوسط) -سفارشی سازی متوسط
  2. VirtoCommerce(فروشگاه‌های تا سایز بزرگ و عملیات تجاری بزرگ) -سفارشی سازی پیشرفته، زمان بر است ولی برای کارهای بزرگ لازم است.
موارد سفارشی 
  1. با ASP.NET چند مورد توسعه داشتیم.
هر کدام از اینها سطح مختلفی از پیچیدگی دارند و بر اساس این پیچیدگی سطوح مختلفی از ماژول‌های تجاری پیشرفته درآنها وجود دارد.
بری مثال در nopCommerce شما C# و ASP.NET و jQuery بلد باشید عمده کار انجام می‌شود. و پروژه لایه بندی پیچیده ای ندارد. شما با یک اپلیکیشن طرف هستید
ولی در VirtoCommerce باید تسلط کافی به مفاهیم برنامه نویسی شی گرا، لایه بندی، معماری سرویس گرا، C# و AngularJs و liquid و چندین مورد دیگر داشته باشید تا پروژه جلو برود. اینجا با چند اپلیکیشن طرف هستید و این پروژه برای اجرا شدن روی shared hosting ساخته نشده است.
آن چیزی که مشتری از یک سیستم ecommerce می‌بیند با چیزی که مدیران و پرسنل مجموعه فروشگاه می‌بینند متفاوت است، در اغلب سیستم‌ها چیزی که مستری می‌بیند تقریبا مشابه است ولی پشت صحنه زمین تا آسمان تفاوت دارد.
پشت صحنه یک فروشگاه اتفاقات زیادی می‌تواند در جریان باشد، چیزی که در بخش مدیریت سفارش nopcommerce وجود دارد ساده است، مدیریت امور مالی، مدیریت تحویل کالا، مدیریت اسناد، مدیریت موجودی و ... می‌تواند بسیار پیچیده‌تر باشد و حتی به کمک نرم افزارهای دیگر یا سرویس‌های آنلاین دیگر مدیریت شود.
Delivery, Payment, Tax, Inventory, Warehouse, Localization, Globalization و موارد متعدد دیگری هر کدام در این فروشگاه‌های آماده در حد نیاز پیاده سازی شده اند، و این نیازی که توسط تیم توسعه آن تعریف شده مشتریان هدف آن را مشخص می‌کند. اگر کمی در marketplace هر کدام از این‌ها چرخی بزنید و ماژول‌های مشابه را بررسی کنید صرفا از تفاوت قیمت و سطح پشتیبانی کیفیت هر کدام مشخص می‌شود.
مثلا ما در یکی از پروژه‌ها VirtoCommerce را به عنوان پایه پروژه انتخاب کردیم ولی بر اساس منطق تجاری تعریف شده ماژول‌های زیادی برای آن توسعه داده شد، حتی تغییراتی در هسته آن ایجاد شد. این پروژه 6 ماه با یک تیم 5 (مدیر پروژه+2 نفر دات نت+ گرافیست+1 نفر آندروید+ 1 نفر IOS) نفره طول کشید. در صورتی که مشابه همین کار را با Prestashop برای یک پروژه 15 درصد کوچکتر با یک تیم 3 نفره در مدت 4 ماه انجام دادیم. تازه در virtocommerce هیچ گزارشی وجود ندارد، همه چیز با PowerBi باید انجام شود.
قیمت اولی تقریبا 4 برابر دومی بود. هر دو پروژه وب سایت و نسخه native موبایل داشته اند.
ما درگیر تکنولوژی وابزار نبودیم چون تیم مسلط به هر کدام را داریم، ولی اگر مثلا فقط به .net مسلط هستید در همان حوزه ادامه دهید. البته PHP هزینه‌های کمتری دارد. 
حرف آخر: حتی در مایکروسافت هم چند وقت یک بار میندازن دور از اول می‌نویسند، رسیدن به ebay کار زیادی می‌برد شاید در طول مسیر حتی چند بار تغییر جهت بدهید. دیجی کالا اصلا اندازه ebay نیست. با هم مقایسه نکنید. در حال حاظر متد‌های تجارت الکترونیک در حال پیشرفت و تحول هستند. دیجیکالا فقط چند متد را در خود دارد فروشگا هایی هستند که چندین متد فروش را همزمان پیاده سازی کرده اند و مدیریت آنها به صورت یکپارچه انجام می‌شود.
یک فروشگاه آنلاین فقط نمای کار است کار فیزیکی پشت صحنه بسیار پیچیده‌تر است.
مطالب
تغییرات Logging در ASP.NET Core 6x
فرض کنید با استفاده از روش متداول زیر، کار ثبت یک واقعه را انجام داده‌اید:
public class TestController
{
    private readonly ILogger<TestController> _logger;
    public TestController(ILogger<TestController> logger)
    {
        _logger = logger;
    }

   [HttpGet("/")]
    public string Get()
    {
        _logger.LogInformation("hello world");
          return "Hello world!";
    }
}
در یک برنامه‌ی متداول ASP.NET Core، زیرساخت کار با ILogger از پیش تنظیم شده‌است. برای کار با آن فقط کافی است به نمونه‌های ILogger و یا <ILogger<T از طریق سیستم تزریق وابستگی‌ها دسترسی یافت و سپس متدهای الحاقی آن‌را مانند LogInformation فراخوانی کرد.

اگر یک چنین برنامه‌ای را به دات نت 6 ارتقاء دهید، با پیام اخطار زیر مواجه خواهید شد:
CA1848: For improved performance, use the LoggerMessage delegates instead of calling LogInformation
به صورت خلاصه، تمام متدهای پیشین LogInformation، LogDebug و امثال آن در دات نت 6 منسوخ شده درنظر گرفته می‌شوند! دلیل آن‌را در ادامه بررسی خواهیم کرد.


استفاده‌ی گسترده از source generators در دات نت 6

source generators، امکان مداخله در عملیات کامپایل برنامه را میسر کرده و امکان تولید کدهای پویایی را در زمان کامپایل، فراهم می‌کنند. هرچند این قابلیت به همراه دات نت 5 ارائه شدند، اما تا زمان دات نت 6 استفاده‌ی گسترده‌ای از آن در خود دات نت صورت نگرفت. موارد زیر، تغییراتی است که بر اساس source generators در دات نت 6 رخ داده‌اند:
- source generators مخصوص ILogger (موضوع این بحث؛ یعنی LoggerMessage source generator)
- source generators مخصوص System.Text.Json تا سربار تبدیل به JSON و یا برعکس کمتر شود.
- بازنویسی مجدد پروسه‌ی کامپایل Blazor/Razor بر اساس source generators، بجای روش دو مرحله‌ای قبلی که امکان Hot Reload را فراهم کرده‌است.

نوشتن یک source generator هرچند ساده نیست، اما چون نیاز به reflection را به حداقل می‌رساند، می‌تواند تغییرات کارآیی بسیار مثبتی را به همراه داشته باشد.


توصیه به استفاده از LoggerMessage.Define در دات نت 6

ILogger به همراه قابلیت‌هایی مانند structural logging نیز هست که امکان فرمت بهتر پیام‌های ثبت شده را میسر می‌کند تا توسط برنامه‌های جانبی که قرار است این لاگ‌ها را پردازش کنند، به سادگی قابل خواندن باشند. برای مثال رکورد زیر را در نظر بگیرید:
public record Person (int Id, string Name);
به همراه نمونه‌ای از آن:
var person = new Person(123, "Test");
خروجی لاگ زیر در این حالت:
_logger.LogInformation("hello to {Person}", person);
به صورت زیر خواهد بود:
info: TestController[0]
hello world to Person { Id = 123, Name = Test }
دقت کنید که رشته‌ی ارسالی به LogInformation به همراه $ نیست. یعنی از string interpolation استفاده نشده‌است و نام پارامتر تعریف شده (placeholder name) با حروف بزرگ شروع شده‌است.

اگر در اینجا مانند مثال زیر از string interpolation استفاده شود:
_logger.LogInformation($"hello world to {person}"); // Using interpolation instead of structured logging
هرچند کار با آن ساده‌تر است از string.Format، اما برای عملیات ثبت وقایع با کارآیی بالا توصیه نمی‌شود؛ به این دلایل:
- ویژگی «لاگ‌های ساختار یافته» را از دست می‌دهیم و دیگر توسط نرم افزارهای ثالث لاگ خوان، به سادگی پردازش نخواهند شد.
- ویژگی «قالب ثابت» پیام را نیز از دست خواهیم داد که باز هم یافتن پیام‌های مشابه را در بین انبوهی از لاگ‌های رسیده مشکل می‌کند.
-  کار serialization شیء ارسالی به آن، پیش از عملیات ثبت وقایع رخ می‌دهد. اما ممکن است سطح لاگ سیستم در این حد نباشد و اصلا این پیام لاگ نشود. در این حالت یک کار اضافی صورت گرفته و بر روی کارآیی برنامه تاثیر منفی خواهد گذاشت.

برای جلوگیری از serialization و همچنین تخصیص حافظه‌ی اضافی و مشکلات عدم ساختار یافته بودن لاگ‌ها، توصیه شده‌است که ابتدا سطح لاگ مدنظر بررسی شود و همچنین از string interpolation استفاده نشود:
if (_logger.IsEnabled(LogLevel.Information))
{
   _logger.LogInformation("hello world to {Person}", person);
}
البته مشکل این روش، تکرار این if/else‌ها در تمام برنامه‌است و همچنین باید دقت داشت که LogLevel انتخابی، با متد لاگ، هماهنگی دارد.
مشکل دیگر لاگ‌های ساختار یافته، امکان فراموش کردن یکی از پارامترها است که با یک خطای زمان اجرا گوشزد خواهد شد؛ مانند مثال زیر:
_logger.LogInformation("hello world to {Person} because {Reason}", person);
اکنون در دات نت 6 با پیام اخطار CA1848 که در ابتدای بحث مشاهده کردید، توصیه می‌کنند که اگر قالب نهایی خاصی را مدنظر دارید، آن‌را توسط متد LoggerMessage.Define دقیقا مشخص کنید:
private static readonly Action<ILogger, Person, Exception?> _logHelloWorld =
    LoggerMessage.Define<Person>(
        logLevel: LogLevel.Information,
        eventId: 0,
        formatString: "hello world to {Person}");
در این روش جدید باید یک Action را برای لاگ کردن پیام‌ها تهیه کرد که از همان ابتدا LogLevel آن مشخص است (و نیازی به بررسی مجزا ندارد؛ یعنی خودش logger.IsEnabled را فراخوانی می‌کند) و همچنین از روش لاگ ساختار یافته استفاده می‌کند. مزیت این روش کش شدن قالب لاگ، در بار اول فراخوانی آن است ( برخلاف متدهای الحاقی مانند LogInformation که هربار باید این قالب‌ها را پردازش کنند) و همچنین در اینجا دیگر خبری از boxing و تبدیل نوع پارامترها نیست.

اکنون روش فراخوانی این Action با کارآیی بالا به صورت زیر است:
[HttpGet("/")]
public string Get()
{
    var person = new Person(123, "Test");
    _logHelloWorld(_logger, person, null);
      return "Hello world!";
}
همانطور که مشاهده می‌کنید اینبار دیگر حتی امکان فراموش کردن پارامتری وجود ندارد (مشکلی که می‌تواند با LogInformation متداول رخ دهد).


معرفی [LoggerMessage] source generator در دات نت 6

هرچند LoggerMessage.Define، مزایای قابل توجهی مانند کش شدن قالب لاگ، عدم نیاز به بررسی ضرورت لاگ شدن پیام و ارسال تعداد پارامترهای صحیح را به همراه دارد، اما ... کار کردن با آن مشکل است و برای کار با آن باید کدهای زیادی را نوشت. به همین جهت با استفاده از قابلیت source generators، امکان تولید خودکار این نوع کدها در زمان کامپایل برنامه پیش‌بینی شده‌است:
public partial class TestController
{
   [LoggerMessage(0, LogLevel.Information, "hello world to {Person}")]
   partial void LogHelloWorld(Person person);
}
این قطعه کد، LoggerMessage.Define را به صورت خودکار برای ما تولید می‌کند. برای اینکار باید یک متد partial را تهیه کرد و سپس آن‌را به ویژگی جدید LoggerMessage مزین کرد. پس از آن source generator، مابقی کارها را در زمان کامپایل برنامه انجام می‌دهد.
ویژگی partial method، امکان تعریف یک متد را در یک فایل و سپس ارائه‌ی پیاده سازی آن‌را در فایلی دیگر میسر می‌کند که البته در اینجا آن فایل دیگر، توسط source generator تولید می‌شود.
باید دقت داشت که در اینجا TestController را نیز باید به صورت partial تعریف کرد تا آن نیز قابلیت بسط در چند فایل را پیدا کند. همچنین متد فوق را به صورت static partial void نیز می‌توان نوشت.

یکی از مزایای کار با source generator که خودش در اصل یک آنالایزر هم هست، بررسی تعداد پارامترهای ارسالی و تعریف شده‌است:
[LoggerMessage(0, LogLevel.Information, "hello world to {Person} with a {Reason}")]
partial void LogHelloWorld(Person person);
برای مثال در اینجا متد LogHelloWorld یک پارامتر دارد اما LoggerMessage آن به همراه دو پارامتر تعریف شده‌است که این مشکل در زمان کامپایل تشخیص داده شده و گوشزد می‌شود (برخلاف روش‌های پیشین که در زمان اجرا این نوع مشکلات نمایان می‌شدند).

در این روش، امکان ذکر پارامتر اختیاری LogLevel هم وجود دارد؛ اگر نیاز است مقدار آن به صورت پویا تغییر کند:
[LoggerMessage(Message = "hello world to {Person}")]
partial void LogHelloWorld(LogLevel logLevel, Person person);
مطالب
بهبود کارآیی LINQ در دات نت 7
LINQ یا همان Language-Integrated Query، یک زبان ساده‌ی کوئری نوشتن یکپارچه‌ی با دات نت است. به کمک آن می‌توان اعمال پیچیده‌ای را بر روی اشیاء، به زبانی ساده بیان کرد و امروزه تقریبا توسط تمام توسعه دهندگان دات نت مورد استفاده قرار می‌گیرد. اما ... این سادگی، بهایی را نیز به همراه دارد: کمتر بودن سرعت اجرا و همچنین افزایش مصرف حافظه. با توجه به گستردگی استفاده‌ی از LINQ، اگر بهبودی در این زمینه حاصل شود، بر روی کارآیی تمام برنامه‌های دات نتی تاثیر خواهد گذاشت و این امر در دات نت 7 محقق شده‌است. کارآیی متدهای LINQ to Objects در دات نت 7 (مانند متدهای Enumerable.Max, Enumerable.Min, Enumerable.Average, Enumerable.Sum) به شدت افزایش یافته و این افزایش گاهی حتی بیشتر از 10 برابر نسبت به نگارش‌های قبلی دات نت است؛ اما چگونه به چنین کارآیی رسیده‌اند؟


تدارک یک آزمایش برای بررسی میزان افزایش کارآیی متدهای LINQ در دات نت 7

در ادامه یک آزمایش ساده‌ی بررسی کارآیی متدهای Enumerable.Max, Enumerable.Min, Enumerable.Average, Enumerable.Sum را با استفاده از کتابخانه‌ی معروف BenchmarkDotNet مشاهده می‌کنید:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Generic;
using System.Linq;


[MemoryDiagnoser(displayGenColumns: false)]
public partial class Program
{
  static void Main(string[] args) =>
    BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);

  [Params (10, 10000)]
  public int Size { get; set; }
  private IEnumerable<int> items;

  [GlobalSetup]
  public void Setup()
  {
    items = Enumerable.Range(1, Size).ToArray();
  }  

  [Benchmark]
  public int Min() => items.Min();

  [Benchmark]
  public int Max() => items.Max();

  [Benchmark]
  public double Average() => items.Average();

  [Benchmark]
  public int Sum() => items.Sum();
}
برای آزمایش آن، یکبار target framework پروژه را بر روی net6.0 و بار دیگر بر روی net7.0 قرار داده و برنامه را اجرا می‌کنیم. خلاصه‌ی مفهومی نتایج حاصل به صورت زیر است که ... شگفت‌انگیز هستند!
در مورد کار با آرایه‌ها:


- زمان اجرای یافتن Min در آرایه‌های کوچک، در دات نت 7، نسبت به دات نت 6، حدودا 10 برابر کاهش یافته و اگر این آرایه بزرگتر شود و برای مثال حاوی 10 هزار المان باشد، این زمان 20 برابر کاهش یافته‌است.
- این کاهش زمان‌ها برای سایر متدهای LINQ نیز تقریبا به همین صورت است؛ منها متد Sum که اندازه‌ی آرایه، تاثیری را بر روی نتیجه‌ی نهایی ندارد.
- همچنین در دات نت 7، با فراخوانی متدهای LINQ، افزایش حافظه‌ای مشاهده نمی‌شود.

در مورد کار با لیست‌ها:


- در دات نت 6، اعمال صورت گرفته‌ی توسط LINQ بر روی آرایه‌ها، نسبت به لیست‌ها، همواره سریعتر است.
- در دات نت 7 هم در مورد مجموعه‌های کوچک، وضعیت همانند دات نت 6 است. اما اگر مجموعه‌ها بزرگتر شوند، تفاوتی بین مجموعه‌ها و آرایه‌ها وجود ندارد و حتی وضعیت مجموعه‌ها بهتر است: کارآیی کار با لیست‌ها 32 برابر بیشتر شده‌است!


اما چگونه در دات نت 7، چنین بهبود کارآیی خیره‌کننده‌ای در متدهای LINQ حاصل شده‌است؟

برای بررسی چگونگی بهبود کارآیی متدهای LINQ در دات نت 7 باید به نحوه‌ی پیاده سازی آن‌ها در نگارش‌های مختلف دات نت مراجعه کرد. برای مثال پیاده سازی متد الحاقی Min تا دات نت 6 به صورت زیر است:
public static int Min(this IEnumerable<int> source)
{
  if (source == null)
  {
    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
  }

  int value;
  using (IEnumerator<int> e = source.GetEnumerator())
  {
    if (!e.MoveNext())
    {
      ThrowHelper.ThrowNoElementsException();
    }

    value = e.Current;
    while (e.MoveNext())
    {
      int x = e.Current;
      if (x < value)
      {
        value = x;
      }
    }
  }
  return value;
}
این متد نسبتا ساده‌است. یک IEnumerable را دریافت کرده و سپس با استفاده از متد MoveNext، مقدار فعلی را با مقدار بعدی مقایسه می‌کند. در این مقایسه، کوچکترین مقدار ذخیره می‌شود تا در نهایت به انتهای مجموعه برسیم.
اما ... پیاده سازی این متد در دات نت 7 متفاوت است:
public static int Min(this IEnumerable<int> source) => MinInteger(source);

private static T MinInteger<T>(this IEnumerable<T> source)
  where T : struct, IBinaryInteger<T>
{
  T value;

  if (source.TryGetSpan(out ReadOnlySpan<T> span))
  {
    if (Vector.IsHardwareAccelerated && 
        span.Length >= Vector<T>.Count * 2)
    {
      .... // Optimized implementation
      return ....;
    }
  }
  .... //Implementation as in .NET 6
}
در اینجا در ابتدا سعی می‌شود تا یک ReadOnlySpan از مجموعه‌ی ارائه شده، تهیه شود. اگر این کار میسر نشد، کدهای همان روش قبلی دات نت 6 که توضیح داده شد، اجرا می‌شود. البته در آزمایشی که ما تدارک دیدیم، چون از لیست‌ها و آرایه‌ها استفاده شده بود، همواره امکان تهیه‌ی یک ReadOnlySpan از آن‌ها میسر است. بنابراین به قسمت اجرایی همانند دات نت 6 نمی‌رسیم.
اما ... ReadOnlySpan چیست؟ نوع‌های Span و ReadOnlySpan، یک ناحیه‌ی پیوسته‌ی مدیریت شده و مدیریت نشده‌ی حافظه را بیان می‌کنند. یک Span از نوع ref struct است؛ یعنی تنها می‌تواند بر روی stack قرار گیرد که مزیت آن، عدم نیاز به تخصیص حافظه‌ی اضافی و بهبود کارآیی است. همچنین ساختار داخلی Span در سی شارپ 11 اندکی تغییر کرده‌است که در آن از ref fields جهت دسترسی امن به این ناحیه‌ی از حافظه استفاده می‌شود. پیشتر از نوع داخلی ByReference برای اشاره به ابتدای این ناحیه‌ی از حافظه استفاده می‌شد که به همراه بررسی امنیتی در این باره نبود.

پس از دریافت ReadOnlySpan، به سطر زیر می‌رسیم:
if (Vector.IsHardwareAccelerated && span.Length >= Vector<T>.Count * 2)
که بررسی می‌کند آیا سخت افرار فعلی از قابلیت‌های SIMD برخوردار است یا خیر؟ اگر بله، اینبار با استفاده از ریاضیات برداری شتاب یافته‌ی توسط سخت افزار، محاسبات را انجام می‌دهد:
private static T MinInteger<T>(this IEnumerable<T> source)
where T : struct, IBinaryInteger<T>
{
  .... 
  if (Vector.IsHardwareAccelerated && span.Length >= Vector<T>.Count * 2)
  {
    var mins = new Vector<T>(span);
    index = Vector<T>.Count;
    do
    {
      mins = Vector.Min(mins, new Vector<T>(span.Slice(index)));
      index += Vector<T>.Count;
    }
    while (index + Vector<T>.Count <= span.Length);

    value = mins[0];
    for (int i = 1; i < Vector<T>.Count; i++)
    {  
      if (mins[i] < value)
      {
        value = mins[i];
      }
    }
  ....
}
بنابراین به صورت خلاصه در دات نت 7 با استفاده از بکارگیری نوع‌های ویژه‌ی Span و نوع‌های برداری شتاب‌یافته‌ی توسط اکثر سخت افزارهای امروزی، سبب بهبود قابل ملاحظه‌ی کارآیی متدهای LINQ شده‌اند.
نظرات اشتراک‌ها
ReSharper 7.1 منتشر شد.
- ابزار Refactoring بهتری نسبت به ابزارهای توکار خود VS.NET داره.
- اگر می‌خواهید خودتون رو عادت بدید به اصول نامگذاری دات نت، بهترین ابزار است. مدام زیر کارهای شما خط خواهد کشید و توصیه می‌کنه.
- امکانات بهتری رو برای Unit testing به همراه داره.
- یک سری از خطاهای کدنویسی رو هم گوشزد می‌کنه به همراه راه حل.
و ...
اشتراک‌ها
یک captcha حرفه‌ای

این کپچا برای دات نت و جاوا و PHP تولید شده و امکانات زیادی داره از قبیل انواع حالات نشان دهنده متن ، حالات خطوط ، رنگ بندی و افکت و همچنین خواندن کد به صورت صوتی و ...

تفاوت نسخه رایگان و تجاری در نمایش لینک به وب سایت خودشون هست ، من در خیلی از پروژه هام از این استفاده می‌کنم

یک captcha حرفه‌ای
مطالب
خواندنی‌های 19 فروردین

- ویدیوی رایگان آموزشی در مورد جنبه‌های مختلف LINQ to Entities (دریافت، ماخذ)

- Mono و پشتیبانی از SIMD یا Single Instruction Multiple Data
برنامه نویسی موازی تنها به برنامه نویسی چند ریسمانی و چند هسته‌ای خلاصه نمی‌شود. بلکه استفاده از توانایی‌های پیشرفته در پروسسورهای مدرن امروزی Intel و AMD نیز توانایی قابل توجهی را در این عرصه ارائه می‌دهند. بسیاری از برنامه‌های نوشته شده به زبان‌های C و CPP از SIMD جهت بالا بردن سرعت پردازشی استفاده می‌کنند ( برای مثال بالا بردن سرعت کار با ماتریس‌ها و بردارها یا بهینه سازی حلقه‌ها) و کامپایلرهای آن‌ها نیز در این زمینه امکانات ویژه‌ای را ارائه ‌می‌نمایند. اما زبان‌های بر پایه دات نت راه ساده‌ای را برای استفاده از این توانایی ندارند.
با ارائه مونو 2.2 (شماره نگارش‌های مونو (دات نت لینوکسی) با شماره نگارش‌های دات نت فریم ورک مایکروسافت همخوانی ندارد و مستقل هستند)، این سناریو تغییر کرده است و فضای نام Mono.Simd ارائه شده است. به این صورت می‌توان از توانایی‌های SIMD (تنها SSE3 و قسمتی از SSE4 پشتیبانی می‌شود) در برنامه‌های دات نت استفاده نمود (که بیشتر بر روی عملیات سریع بر روی ماتریس‌ها و بردارها متمرکز شده است).
جهت اطلاعات بیشتر می‌توان به دمویی در اینباره رجوع کرد. دریافت
ماخذ

- کارت‌های مرجع دات نت
سایت Dzone اخیرا در تکمیل برگه‌های مرجع پیشین خود، برگه‌های مرجع ASP.Net را نیز ارائه کرده است.
Core ASP.NET
برای دریافت نیاز به ثبت نام است و سپس درخواست لینک دانلود که به آدرس ایمیل شما ارسال خواهد شد.

مطالب
Static Reflection

قابلیت Dynamic reflection یا به اختصار همان reflection متداول، از اولین نگارش‌های دات نت فریم در دسترس است و امکان دسترسی به اطلاعات مرتبط با کلاس‌ها، متدها، خواص و غیره را در زمان اجرا مهیا می‌سازد. تابحال به کمک این قابلیت، امکان تهیه‌ی ابزارهای پیشرفته‌ی زیر مهیا شده است:
انواع و اقسام
- فریم ورک‌های آزمون واحد
- code generators
- ORMs
- ابزارهای آنالیز کد
و ...


برای مثال فرض کنید که می‌خواهید برای یک کلاس به صورت خودکار، متدهای آزمون واحد تهیه کنید (تهیه یک code generator ساده). اولین نیاز این برنامه، دسترسی به امضای متدها به همراه نام آرگومان‌ها و نوع آن‌ها است. برای حل این مساله باید برای مثال یک parser زبان سی شارپ یا اگر بخواهید کامل‌تر کار کنید، به ازای تمام زبان‌های قابل استفاده در دات نت فریم ورک باید parser تهیه کنید که ... کار ساده‌ای نیست. اما با وجود reflection به سادگی می‌توان به این نوع اطلاعات دسترسی پیدا کرد و نکته‌ی مهم آن هم این است که مستقل است از نوع زبان مورد استفاده. به همین جهت است که این نوع ابزارها را در فریم ورک‌هایی که فاقد امکانات reflection هستند، کمتر می‌توان یافت. برای مثال کیفیت کتابخانه‌های آزمون واحد CPP در مقایسه با آنچه که در دات نت مهیا هستند، اصلا قابل مقایسه نیستند. برای نمونه به یکی از معظم‌ترین فریم ورک‌های آزمون واحد CPP که توسط گوگل تهیه شده مراجعه کنید : (+)
قابلیت Reflection ، مطلب جدیدی نیست و برای مثال زبان جاوا هم سال‌ها است که از آن‌ پشتیبانی می‌کند. اما نگارش سوم دات نت فریم ورک با معرفی lambda expressions ، LINQ و Expressions در یک سطح بالاتر از این Dynamic reflection متداول قرار گرفت.

تعریف Static Reflection :
استفاده از امکانات Reflection API بدون بکارگیری رشته‌ها، به کمک قابلیت اجرای به تعویق افتاده‌ی LINQ، جهت دسترسی به متادیتای المان‌های کد، مانند خواص، متدها و غیره.
برای مثال کد زیر را در نظر بگیرید:
//dynamic reflection
PropertyInfo property = typeof (MyClass).GetProperty("Name");
MethodInfo method = typeof (MyClass).GetMethod("SomeMethod");
این کد، یک نمونه از دسترسی به متادیتای خواص یا متدها را به کمک Reflection متداول نمایش می‌دهد. مهم‌ترین ایراد آن استفاده از رشته‌ها است که تحت نظر کامپایلر نیستند و تنها زمان اجرا است که مشخص می‌شود آیا MyClass واقعا خاصیتی به نام Name داشته است یا خیر.
چقدر خوب می‌شد اگر این قابلیت بجای dynamic بودن (مشخص شدن در زمان اجرا)، استاتیک می‌بود و در زمان کامپایل قابل بررسی می‌شد. این امکان به کمک lambda expressions و expression trees دات نت سه بعد، میسر شده است. کلیدهای اصلی Static Reflection کلاس‌های Func و Expression هستند. با استفاده از کلاس Func می‌توان lambda expression ایی را تعریف کرد که مقداری را بر می‌گرداند و توسط کلاس Expression می‌توان به محتوای یک delegate دسترسی یافت. ترکیب این دو، قدرت دستیابی به اطلاعاتی مانند PropertyInfo را در زمان طراحی کلاس‌ها، می‌دهد؛ با توجه به اینکه:
- کاملا توسط intellisense موجود در VS.NET پشتیبانی می‌شود.
- با استفاده از ابزارهای refactoring قابل کنترل است.
- از همه مهم‌تر، دیگری خبری از رشته‌ها نبوده و همه چیز تحت کنترل کامپایلر قرار می‌گیرد.

و شاید هیچ قابلیتی به اندازه‌ی Static Reflection در این چندسال اخیر بر روی اکوسیستم دات نت فریم ورک تاثیرگذار نبوده باشد. این روزها کمتر کتابخانه یا فریم ورکی را می‌توانید پیدا کنید که از Static Reflection استفاده نکند. سرآغاز استفاده گسترده از آن به Fluent NHibernate بر می‌گردد؛ سپس در انواع و اقسام mocking frameworks‌ ، ORMs و غیره استفاده شد و مدتی است که در ASP.NET MVC نیز مورد استفاده قرار می‌گیرد (برای مثال TextBoxFor معروف آن):
public string TextBoxFor<T>(Expression<Func<T,object>> expression);
به این ترتیب حین استفاده از آن دیگری نیازی نخواهد بود تا نام خاصیت مدل مورد نظر را به صورت رشته وارد کرد:
<%= this.TextBoxFor(model => model.FirstName); %>

یک مثال ساده از تعریف و بکارگیری Static Reflection :
public PropertyInfo GetProperty<T>(Expression<Func<T, object>> expression)
{
var memberExpression = expression.Body as MemberExpression;

if (memberExpression == null)
throw new InvalidOperationException("Not a member access.");

return memberExpression.Member as PropertyInfo;
}
همانطور که عنوان شد کلیدهای اصلی بهر‌ه‌گیری از امکانات Static reflection ، استفاده از کلاس‌های Expression و Func هستند که در آرگومان متد فوق بکارگرفته شده‌اند و در حقیقت یک expression of a delegate است که به آن Lambdas as Data نیز گفته می‌شود. این delegate پارامتری از نوع T را دریافت کرده و سپس مقداری از نوع object را بر می‌گرداند. اما زمانیکه از کلاس Expression در اینجا استفاده می‌شود، این Func دیگر اجرا نخواهد شد، بلکه از آن به عنوان قطعه‌ کدی که اطلاعاتش قرار است استخراج شود (Lambdas as Data) استفاده می‌شود.
برای نمونه Fluent NHibernate‌ در پشت صحنه متد Map ، به کمک متدی شبیه به GetProperty فوق، a => a.Address1 را به رشته متناظر خاصیت Address1 تبدیل کرده و جهت تعریف نگاشت‌ها مورد استفاده قرار می‌دهد:
public class AddressMap : DomainMap<Address>
{
public AddressMap()
{
Map(a => a.Address1);
}
}

جهت اطلاع؛ قابلیت استفاده از «کد به عنوان اطلاعات» هم مفهوم جدیدی نیست و برای مثال زبان Lisp چند دهه است که آن‌را ارائه داده است!

برای مطالعه بیشتر: