نظرات مطالب
Blazor 5x - قسمت 34 - توزیع برنامه‌های Blazor بر روی IIS
یک نکته‌ی تکمیلی: بهبود IL Trimming در NET 6x.
در دات نت 5، IL Trimming فقط اسمبلی‌های استفاده نشده را حذف می‌کند. در دات نت 6، این حالت پیش‌فرض به link تغییر پیدا کرده؛ یعنی نه فقط اسمبلی‌های استفاده نشده را حذف می‌کند، بلکه متدها و اعضایی را هم که در برنامه استفاده نشده‌اند نیز حذف می‌کند.
نظرات اشتراک‌ها
انتشار نسخه اولیه NET Core 2.0. (عمومی)
- کتابخانه‌های ثالث کار با تصاویر مخصوص NET Core.
+ برای  NET Core 2x. : مستندات رسمی بازگشت فضای نام System.​Drawing (تحت ویندوز از همان +GDI، دقیقا مانند دات نت کامل استفاده می‌کند)
اشتراک‌ها
4 پیش بینی در مورد آینده‌ی دنیای دات نت

- NET Standard. با نگارش بعدی NET. دیگر توسعه‌ی آنچنانی نخواهد یافت.

- Visual Studio مبتنی بر دات نت 5 یا 6 تهیه شده و همچنین 64 بیتی خواهد بود.

- شاهد یک UI Framework چندسکویی خواهیم بود.

و ...

4 پیش بینی در مورد آینده‌ی دنیای دات نت
مطالب
امکان استفاده‌ی مستقیم از کتابخانه‌های Full .NET Framework در NET Core 2.0.
یکی از مواردی که به همراه NET Core 1.x. وجود دارد، کمبود کتابخانه‌های ثالث مخصوص آن است. برای مثال کتابخانه‌ی log4net در اوایل ارائه‌ی NET Core. نگارش مخصوص به آن‌را نداشت (البته هم اکنون دارد). باید درنظر داشت، این مورد صرفا در حالت توزیع چندسکویی برنامه‌های مبتنی بر NET Core. مشکل ایجاد می‌کرد. از این جهت که می‌توان full .NET framework را به عنوان Target Framework برنامه‌های NET Core. معرفی کرد و در این حالت برنامه بدون هیچگونه مشکلی تنها بر روی ویندوز و سرورهای ویندوزی اجرا می‌شود (و امکان دسترسی به تمامی کتابخانه‌های مخصوص full .NET framework را نیز دارا خواهد بود)؛ اما قابلیت توزیع بر روی لینوکس و مک را از دست خواهد داد.
در NET Core 2.0. از یک اصطلاحا «compatibility shim» مخصوص استفاده می‌شود که امکان افزودن ارجاعات به full framework library‌ها را بدون نیاز به تغییر target framework برنامه میسر می‌کند. یعنی در اینجا می‌توان یک کتابخانه‌ی قدیمی دات نتی را در برنامه‌های مبتنی بر NET Core. بر روی لینوکس نیز اجرا کرد و در این حالت نیازی به تبدیل اجباری این کتابخانه به نسخه‌ی NET Core. آن نیست.


NET Core 2.0. پیاده سازی کننده‌ی NET Standard 2.0. است

NET Standard‌. در حقیقت یک قرار داد است که سکوهای کاری مختلف دات نتی مانند Full .NET Framework ، Xamarin ، Mono ، UWP و غیره می‌توانند آن‌را پیاده سازی کنند. یک نمونه‌ی دیگر این پیاده سازی‌ها نیز NET Core. است. برای مثال دات نت 4.6.1، استاندارد و قرار داد شماره‌ی 2 دات نت را پیاده سازی می‌کند. به همین صورت NET Core 2.0. نیز پیاده سازی کننده‌ی این استاندارد شماره 2 است.
 با تغییرات اخیر، اکنون NuGet می‌تواند کتابخانه‌های مبتنی بر NET Standard 2. را در برنامه‌های مبتنی بر سکوهای کاری که آن‌را پیاده سازی می‌کنند، بدون مشکل اضافه کند. برای مثال می‌توان اسمبلی‌های دات نت 4.6.1 را به برنامه‌های ASP.NET Core 2.0 اضافه کرد (کاری که در نگارش 1x آن به صورت مستقیم میسر نیست) و یا می‌توان اسمبلی‌های کامپایل شده‌ی برای دات نت استاندارد 2 را به برنامه‌های مبتنی بر دات نت 4.6.1 اضافه کرد.


آیا واقعا کتابخانه‌های قدیمی دات نتی توسط برنامه‌های NET Core 2.0. در لینوکس نیز اجرا خواهند شد؟

دات نت استاندارد، بیش از یک قرار داد چیزی نیست و پیاده سازی کنندگان آن می‌توانند سطح بیشتری را نسبت به این قرار داد نیز لحاظ کنند. برای مثال دات نت 4.6.1 شامل سطح API بیشتری از دات نت استاندارد 2 است.
 به همین جهت باید درنظر داشت که امکان اضافه کردن یک بسته‌ی نیوگت از یک کتابخانه‌ی نوشته شده‌ی برای دات نت کامل در برنامه‌های دات نت Core به معنای تضمینی برای کار کردن آن در زمان اجرا نخواهد بود. از این جهت که دات نت کامل، به همراه قسمت‌هایی است که در NET Standard. وجود خارجی ندارند. بنابراین اگر کتابخانه‌ی استفاده شده صرفا این API مشترک را هدف قرار داده‌است، هم قابلیت اتصال و هم قابلیت اجرا را خواهد داشت؛ اما اگر برای مثال کسی بسته‌ی NServiceBus را به پروژه‌ی ASP.NET Core 2.0 اضافه کند، بدون مشکل کامپایل خواهد شد. اما از آنجائیکه این کتابخانه از MSMQ استفاده می‌کند که خارج از میدان دید این استاندارد است، در زمان اجرا با شکست مواجه خواهد شد.


«compatibility shim» در NET Standard 2.0. چگونه کار می‌کند؟

در NET Core.، پیاده سازی Object در System.Runtime قرار دارد و کد تولید شده‌ی توسط آن یک چنین ارجاعی را [System.Runtime]System.Object تولید می‌کند. اما در دات نت کلاسیک، System.Object در mscorlib قرار دارد. به همین جهت زمانیکه سعی کنید اسمبلی‌های دات نت کلاسیک را در NET Core 1.x. استفاده کنید، پیام یافتن نشدن نوع‌ها را دریافت خواهید کرد. اما در NET Core 2.0. یک پیاده سازی صوری (facade) از mscorlib وجود دارد که کار آن هدایت نوع درخواستی، به نوع واقعی پیاده سازی شده‌ی در NET Core. است.


در این تصویر استفاده‌ی از یک کتابخانه‌ی ثالث را مشاهده می‌کنید که ارجاعی را به [mscorlib]Microsoft.Win32.RegistryKey دارد (مبتنی بر دات نت کلاسیک است).  همچنین یک mscorlib مشخص شده‌ی به صورت facade را نیز مشاهده می‌کنید. کار آن هدایت درخواست نوع واقع شده‌ی در mscorlib، به نوع موجود [Microsoft.Win32.Registry] Microsoft.Win32.RegistryKey است و تنها زمانی کار خواهد کرد که Microsoft.Win32.RegistryKey.dll وجود خارجی داشته باشد. به این معنا که رجیستری، یک مفهوم ویندوزی است و این کتابخانه بر روی ویندوز بدون مشکل کار می‌کند. اما تحت لینوکس، این قسمت خاص با پیام PlatformNotSupportedException خاتمه خواهد یافت. اما اگر قسمت‌هایی از این کتابخانه را استفاده کنید که در تمام سکوهای کاری وجود داشته باشند، بدون مشکل قادر به استفاده‌ی از آن خواهید بود.


یک مثال: استفاده از کتابخانه‌ی رمزنگاری اطلاعات Inferno

آخرین نگارش کتابخانه‌ی رمزنگاری اطلاعات Inferno مربوط به NET 4.5.2. است. مراحل ذیل را پس از نصب SDK جدید NET Core 2.0. در خط فرمان طی می‌کنیم:
الف) ایجاد پوشه‌ی UseNET452InNetCore2 و سپس ایجاد یک پروژه‌ی کنسول جدید
dotnet new console

ب) افزودن بسته‌ی نیوگت Inferno به پروژه
 dotnet add package Inferno
این بسته بدون مشکل اضافه می‌شود؛ البته پیام اخطار ذیل نیز صادر خواهد شد (چون مبتنی بر NET 4.6.1. که پیاده سازی کننده‌ی NET Standard 2.0. است، نیست):
 log  : Installing Inferno 1.4.0.
warn : Package 'Inferno 1.4.0' was restored using '.NETFramework,Version=v4.6.1' instead of the project target framework '.NETCoreApp,Version=v2.0'. This package may not be fully compatible with your project.
info : Package 'Inferno' is compatible with all the specified frameworks in project 'D:\UseNET452InNetCore2\UseNET452InNetCore2.csproj'.
info : PackageReference for package 'Inferno' version '1.4.0' added to file 'D:\UseNET452InNetCore2\UseNET452InNetCore2.csproj'.
ابتدا پیام می‌دهد که این بسته ممکن است با NET Core 2.0. سازگار نباشد. سپس عنوان می‌کند که سازگاری کاملی را با پروژه‌ی جاری دارد و بسته را اضافه می‌کند.

ج) استفاده از کتابخانه‌ی Inferno جهت تولید یک عدد تصادفی thread safe
using System;
using SecurityDriven.Inferno;

namespace UseNET452InNetCore2
{
    class Program
    {
        static CryptoRandom random = new CryptoRandom();
        static void Main(string[] args)
        {
            Console.WriteLine($"rnd: {random.NextLong()}");
        }
    }
}

د) اجرای برنامه
در ادامه اگر دستور dotnet run را صادر کنیم، ابتدا اخطاری را صادر می‌کند که این بسته ممکن است دارای قسمت‌هایی باشد که با NET core 2.0. سازگار نیست و سپس خروجی نهایی را بدون مشکل اجرا کرده و نمایش می‌دهد.
 >dotnet run
warning NU1701:  This package may not be fully compatible with your project.
rnd: 8167886599578111106
اشتراک‌ها
ساختاری با چند کلید Multikey Dictionary

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

ساختاری با چند کلید Multikey Dictionary
مطالب
راه اندازی وب سایت سریع و سبک با Nancy
Nancy یک فریم ورک سبک برای ساخت سرویس‌های مبتنی بر HTTP بر روی .Net و Mono و در واقع پیاده سازی Sinatra در   Ruby برای .net است. با استفاده از این کتابخانه شما می‌توانید به سادگی درخواست‌های مختلف کاربران را از طریق وب پاسخ دهید. از ویژگی‌های این کتابخانه امکان اجرای آن بدون نیاز به وجود وب سرور و به صورت Standalone می‌باشد.
بهتر است وارد عمل شویم و ببینیم این سیستم چگونه عمل می‌کند. برای شروع ما خود Asp .net را به عنوان میزبان در نظر می‌گیریم.
- یک پروژه خالی Asp .net ایجاد کنید. (Asp .net Empty Web Application)
- وارد خط فرمان Package Manager شوید و عبارت زیر را وارد کنید:
Install-Package Nancy.Hosting.Aspnet
- پروژه‌های Nancy از تعدای ماژول تشکیل شده اند که می‌توانیم برای هر ماژول آدرس وب جداگانه ای در نظر بگیریم.
یک کلاس به پروژه اضافه کنید و نام آن را TestModule بگذارید.
در متن کلاس عبارات زیر را تایپ کنید:
public class TestModule : NancyModule 
{
    public TestModue() 
    {
        Get["/"] = x => "Welcome to my site!";
        Get["/Hello/"] = x=> "Hello Nancy!";
        Get["/Bye/{name}"] = x=> "Good bye " + x.name;
    }
}

حال کلید F5 را زده و برنامه را اجرا کنید.
حالا در مرورگر خودتان عبارت http://localhost:12345/Hello را تایپ کنید. توجه کنید که به جای 12345 باید شماره پورتی که وب سرور دات نت اجراست تایپ کنید.
همانطور که متوجه شدید ما در خطوط بالا تعیین کرده ایم که برای درخواست‌های از نوع Get که مسیر ریشه سایت را درخواست می‌کنند عبارت Welcome to my site! ارسال شود. همچنین برای درخواست هایی که مسیر /Hello را درخواست می‌کنند عبارت Hello Nancy نمایان می‌شود.
نکته جالب برای درخواست‌های /Bye است. در اینجا ما یک پارامتر به نام name تعریف کرده ایم و گفته ایم که درخواست‌های Bye که در ادامه آنها عبارتی وجود دارد به صورت Good bye به همراه عبارت بازگردانده شوند.
همین عملیات برای درخواست‌های Put و Head و سایر انواع درخواست وجود دارد.
برای اینکه درخواست‌ها از مسیر خاصی فراخوانی شوند کافی است در هنگام اعلان سازنده کلاس ماژول، مسیر را تعیین کنید.
public class TestModule : NancyModule
{
    public TestModule() : base("/test")
    {
        Get["/user"] = x=> "It is test for user";
    }
}

این درخواست‌ها از مسیری شبیه این مسیر فراخوانی خواهند شد:
http://localhost:12345/test/user
همانطور که برای پردازش درخواست از عبارات کوتاه استفاده کردیم می‌توانیم از توابع هم استفاده کنیم.
Get["/hello/{username}"] = x=> {
     // some code
     // ...
     // ...
     return "Hello, " + username;
};

همچنین امکان بازگرداندن کدهای وضعیت به طور مستقیم وجود دارد.
Get["/user"] = x=> return 200;

و یا
Get["/user] = x=> return HttpStatusCode.OK;

همانطور که گفته شد امکان میزبانی پروژه‌های Nancy از داخل برنامه‌های دات نتی هم وجود دارد. در مقاله بعدی به این موضوع خواهیم پرداخت.
 
مطالب
امکان مفهوم بخشیدن به رشته‌ها در NET 7.
رشته‌ها، یکی از عمومی‌ترین نوع‌های داده‌ها هستند؛ از آن‌ها در تعریف آدرس‌های اینترنتی، عبارات باقاعده و یا حتی زمان‌ها و تاریخ‌ها استفاده می‌کنیم. در دات نت 7 می‌توان با استفاده از ویژگی جدید StringSyntaxAttribute، به این نوع‌های مختلف اندکی معنا بخشید.


معرفی ویژگی جدید StringSyntax

با استفاده از ویژگی StringSyntax جدید می‌توان مقدار مورد انتظار از رشته‌ی درخواستی را معنادار کرد. برای مثال، Visual Studio سال‌هاست که راهنمایی را در حین تعریف عبارات باقاعده ظاهر می‌کند. اما این راهنما صرفا مختص به ویژوال استودیو است و تا پیش از این راهی وجود نداشت تا عنوان کنیم که برای مثال این رشته قرار است تنها یک عبارت باقاعده باشد. اکنون در دات نت 7 با معرفی ویژگی جدید StringSyntax می‌توان یک چنین intellisense ای را در سایر IDEها نیز شاهد بود.
برای نمونه مثال زیر را درنظر بگیرید:
using System.Diagnostics.CodeAnalysis;

namespace CS11Tests;

public class StringSyntaxAttributeTests
{
    public static void Test()
    {
        RegexTest("");
        DateTest("");
    }

    private static void RegexTest([StringSyntax(StringSyntaxAttribute.Regex)] string regex)
    {
    }

    private static void DateTest([StringSyntax(StringSyntaxAttribute.DateTimeFormat)] string dateTime)
    {
    }
}
در اینجا با استفاده از ویژگی StringSyntax، دقیقا مشخص کرده‌ایم که هدف از تعریف پارامترهای رشته‌ای مدنظر چه چیزی بوده‌است. به این ترتیب، برای مثال در Rider، در حین استفاده از این متدها، به intellisense‌های زیر خواهیم رسید:

راهنمای ظاهر شده جهت تعریف ساده‌تر عبارات باقاعده:


و راهنمای ظاهر شده جهت تعریف ساده‌تر یک DateTime:



امکان استفاده از StringSyntax در دات نت‌های پیش از نگارش 7

هرچند StringSyntax در دات نت 7 تعریف شده‌است؛ اما اگر تعریف کلاس زیر را به همراه فضای نام دقیق آن به پروژه‌های قدیمی‌تر هم اضافه کنیم ... برای دات نت‌های پیش از نگارش 7 هم کار می‌کند:
#if !NET7_0_OR_GREATER

namespace System.Diagnostics.CodeAnalysis
{
  /// <summary>Specifies the syntax used in a string.</summary>
  [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
  public sealed class StringSyntaxAttribute : Attribute
  {
    /// <summary>The syntax identifier for strings containing composite formats for string formatting.</summary>
    public const string CompositeFormat = "CompositeFormat";
    /// <summary>The syntax identifier for strings containing date format specifiers.</summary>
    public const string DateOnlyFormat = "DateOnlyFormat";
    /// <summary>The syntax identifier for strings containing date and time format specifiers.</summary>
    public const string DateTimeFormat = "DateTimeFormat";
    /// <summary>The syntax identifier for strings containing <see cref="T:System.Enum" /> format specifiers.</summary>
    public const string EnumFormat = "EnumFormat";
    /// <summary>The syntax identifier for strings containing <see cref="T:System.Guid" /> format specifiers.</summary>
    public const string GuidFormat = "GuidFormat";
    /// <summary>The syntax identifier for strings containing JavaScript Object Notation (JSON).</summary>
    public const string Json = "Json";
    /// <summary>The syntax identifier for strings containing numeric format specifiers.</summary>
    public const string NumericFormat = "NumericFormat";
    /// <summary>The syntax identifier for strings containing regular expressions.</summary>
    public const string Regex = "Regex";
    /// <summary>The syntax identifier for strings containing time format specifiers.</summary>
    public const string TimeOnlyFormat = "TimeOnlyFormat";
    /// <summary>The syntax identifier for strings containing <see cref="T:System.TimeSpan" /> format specifiers.</summary>
    public const string TimeSpanFormat = "TimeSpanFormat";
    /// <summary>The syntax identifier for strings containing URIs.</summary>
    public const string Uri = "Uri";
    /// <summary>The syntax identifier for strings containing XML.</summary>
    public const string Xml = "Xml";

    /// <summary>Initializes the <see cref="T:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute" /> with the identifier of the syntax used.</summary>
    /// <param name="syntax">The syntax identifier.</param>
    public StringSyntaxAttribute(string syntax)
    {
      this.Syntax = syntax;
      this.Arguments = Array.Empty<object>();
    }

    /// <summary>Initializes the <see cref="T:System.Diagnostics.CodeAnalysis.StringSyntaxAttribute" /> with the identifier of the syntax used.</summary>
    /// <param name="syntax">The syntax identifier.</param>
    /// <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
    public StringSyntaxAttribute(string syntax, params object?[] arguments)
    {
      this.Syntax = syntax;
      this.Arguments = arguments;
    }

    /// <summary>Gets the identifier of the syntax used.</summary>
    public string Syntax { get; }

    /// <summary>Gets the optional arguments associated with the specific syntax employed.</summary>
    public object?[] Arguments { get; }
  }
}

#endif
نظرات مطالب
روش نادرست اعمال دسترسی کاربر به منوها و کنترلهای فرم در windows form ها
سلام
مشکل درست است ولی راه حل ساده است.
بهتر است بر اساس دسترسی کاربر مورد نظر منوها و کنترل‌های روی صفحه در هنگام اجرا ایجاد گردند.
در دات نت کنترلی(FlowLayoutPanel) هم برای مرتب سازی خودکار کنترل‌های ایجاد شده در هنگام اجرا وجود دارد که قضیه را بسیار ساده می‌کند.