امکان مفهوم بخشیدن به رشته‌ها در 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
  • #
    ‫۱ سال و ۷ ماه قبل، جمعه ۲۳ دی ۱۴۰۱، ساعت ۱۱:۱۴
    یک نکته‌ی تکمیلی: امکان مشخص کردن نوع زبان مورد استفاده، توسط StringSyntaxAttribute در Rider


    اگر از Rider استفاده می‌کنید، آخرین نگارش آن، امکان ذکر تمام زبان‌های پشتیبانی شده‌ی توسط Rider را به عنوان پارامتر ویژگی StringSyntax دارد (مانند Regular expressions, JavaScript, HTML, CSS, JSON, XML, SQL) که نمونه‌ای از آن‌را در مثال فوق با ذکر #C ملاحظه می‌کنید. پیشتر یک چنین قابلیتی تنها با استفاده از LanguageInjectionAttribute آن میسر بود.
  • #
    ‫۱ سال و ۷ ماه قبل، شنبه ۲۴ دی ۱۴۰۱، ساعت ۱۴:۱۷
    یک نکته‌ی تکمیلی: پشتیبانی از CompositeFormat توسط StringSyntax 

    یکی از مواردی که توسط ویژگی جدید StringSyntax قابل تنظیم است، [StringSyntax(StringSyntaxAttribute.CompositeFormat)] می‌باشد که جهت پشتیبانی از Composite formatting ارائه شده‌است و هدف از آن، پردازش بهتر متدهایی مانند String.Format است. یعنی با درج قالبی مانند {index[,alignment][:formatString]} می‌توان سبب شد تا اگر آرگومانی مقدار دهی نشده‌است، اخطاری دریافت شود و یا اگر در IDE آرگومانی انتخاب شد، مقدار متناظر با آن، با رنگی مشخص، انتخاب شود.
    این تغییرات قرار است به صورت گسترده‌ای به دات نت 8 اعمال شوند. برای مثال تا دات نت 7، امضای متد WriteLine به صورت زیر است:
    public static void WriteLine(string format, object? arg0)
    اما در دات نت 8 به شکل زیر بهبود خواهد یافت:
    public static void WriteLine([StringSyntax(StringSyntaxAttribute.CompositeFormat)] string format, object? arg0)
    به این صورت استفاده کننده دقیقا می‌داند که باید اصول Composite formatting را در اینجا رعایت کند؛ وگرنه هشدارهای لازم را دریافت خواهد کرد.