ویرایش سوم JavaScript Step by Step بر اساس دو ویرایش قبلی نگارش شده است. با این که معماری اصلی زبان جاوا اسکریپت تغییر آن چنانی نکرده است، استفاده از جاوا اسکریپت هر روزه بیشتر میشود و در طی چند سال اخیر اهمیت آن برای توسعه دهندگان بسیار افزایش یافته است. با این اوصاف ساختار و کلیات کتاب پیش رو تغییری نکرده به جز چند تغییر قابل توجه. بخش Event Handling مورد تاکید بیشتری قرار گرفته است و برای افزایش سرعت توسعه از jQuery استفاده شده است. همچنین در فصل آخر، بخشی برای توسعه برنامههای Windows 8 با استفاده از جاوا اسکریپت در نظر گرفته شده است. با این حال، محتویات این کتاب کاملا در انحصار مایکروسافت نیست!
همه ما با ابزار تزریق وابستگی مایکروسافت کار کردهایم و میدانیم برای معرفی وابستگیها میبایست آنها را به IServiceCollection معرفی کنیم. اما راه حل سادهتری هم وجود دارد. چیزی که در ابزارهای java-spring به صورت خودکار و با استفاده از annotationهایی که در component models تعریف میشوند اینکار را تسهیل میکند و دیگر خبری از یک فایل شلوغ برای معرفی وابستگیها به موتور تزریق وابستگی نیست. برای اینکار در c-sharp با استفاده از موتور تزریق وابستگی مایکروسافت، Reguto را آماده کردم و بسیار ساده با استفاده از attributeهایی که به صورت پیشفرض تعریف شده است میتوانید وابستگیهای خود را معرفی کنید.
نظرات اشتراکها
شبکه اجتماعی فیس نما هک شد
استفاده از اسکریپت آماده برای پروژه به این بزرگی !
اشتراکها
قالب های آماده Bootstrap
نظرات مطالب
آموزش سیلورلایت 4 - قسمتهای 21 تا 27
به خاطر مجموعه خوبی که آماده کردید، سپاسگذارم
نظرات مطالب
ویدیوهای رایگان آموزش jQuery
باتشکر.
دو قسمت دیگرش هم آماده شده.
دو قسمت دیگرش هم آماده شده.
اشتراکها
دریافت کتاب Node.js in Action
جاوا اسکریپت سمت سرور؟ Node.js جاوا اسکریپت سمت سرور است که توانایی پشتیبانی از برنامههای تحت وب مقیاس پذیر و عملکرد بالا را دارد. با استفاده از I/O ناهمگام، سرور توانایی انجام بیش از یک کار در یک لحظه را دارد که این یک احتیاج کلیدی برای برنامههای بلادرنگ تحت وب به مانند چت، بازیها و آمارهای لحظه به لحظه است. همچنین چون زبان برنامه نویسی جاوا اسکریپت است، شما تا انتها هم از همین زبان برای برنامه نویسی استفاده میکنید.
یک مثال: پیاده سازی INotifyPropertyChanged توسط Source Generators
هدف از اینترفیس INotifyPropertyChanged که به همراه یک رخداد است:
مطلع سازی استفاده کنندهی از یک شیء، از تغییرات رخدادهی در مقادیر خواص آن است که نمونهی آن، در برنامههای WPF، جهت به روز رسانی UI، زیاد مورد استفاده قرار میگیرد. البته این رخداد به خودی خود کار خاصی را انجام نمیدهد و برای استفادهی از آن، باید مقدار زیادی کد نوشت و این مقدار کد نیز باید به ازای تک تک خواص یک کلاس مدل، تکرار شوند:
همچنین باید درنظر داشت که با تغییر نام خاصیتی، میزان قابل ملاحظهای از این کدهای تکراری نیز باید به روز رسانی شوند که این عملیات میتواند ایدهی خوبی برای استفادهی از Source Generators باشد.
اگر بخواهیم تولید این کدهای تکراری را به Source Generators محول کنیم، میتوان برای مثال فیلد خصوصی مرتبط را نگه داشت و تولید مابقی کدها را خودکار کرد:
در این حالت کلاس مدل، به صورت partial تعریف میشود و فقط فیلد خصوصی، در کدهای ما حضور خواهد داشت. مابقی کدهای این کلاس partial به صورت خودکار توسط یک Source Generator سفارشی تولید خواهد شد. همانطور که ملاحظه میکنید، کاهش حجم قابل ملاحظهای حاصل شده و همچنین اگر فیلد خصوصی دیگری نیز در اینجا اضافه شود، واکنش Source Generator ما آنی خواهد بود و بلافاصله کدهای مرتبط را تولید میکند و برنامه، بدون مشکلی کامپایل خواهد شد؛ هرچند به ظاهر INotifyPropertyChanged ذکر شده، در این کلاس اصلا پیاده سازی نشدهاست.
ایجاد پروژهی Source Generator
در ابتدا برای ایجاد تولید کنندهی خودکار کدهای INotifyPropertyChanged، یک class library را به solution جاری اضافه میکنیم. سپس نیاز است ارجاعاتی را به دو بستهی نیوگت زیر نیز افزود:
سپس کلاس جدید NotifyPropertyChangedGenerator را به نحو زیر به آن اضافه میکنیم:
- این کلاس باید اینترفیس ISourceGenerator را پیاده سازی کرده و همچنین مزین به ویژگی Generator باشد.
- اینترفیس ISourceGenerator به همراه دو متد Initialize و Execute است که در صورت نیاز باید پیاده سازی شوند.
در متد Execute، به خاصیت context.Compilation دسترسی داریم. این خاصیت تمام اطلاعاتی را که کامپایلر از Solution جاری در اختیار دارد، به توسعه دهنده ارائه میدهد. برای نمونه پیاده سازی متد Execute تولید کنندهی کد مثال جاری، چنین شکلی را دارد:
در اینجا با استفاده از context.Compilation به اطلاعات کامپایلر دسترسی پیدا کرده و سپس SyntaxTrees آنرا یکی یکی، جهت یافتن کلاسها و یا همان ClassDeclarationSyntax ها، پیمایش و بررسی میکنیم. سپس از بین این کلاسها، کلاسهایی که INotifyPropertyChanged را پیاده سازی کرده باشند، انتخاب میکنیم که اطلاعات آن در پایان کار، به متد GeneratePropertyChanged جهت تولید مابقی کدهای partial class ارسال شده و کد تولیدی، به context اضافه میشود تا به نحو متداولی همانند سایر کدهای برنامه، به مجموعه کدهای مورد بررسی کامپایلر اضافه شود.
نکتهی مهم و جالب در اینجا این است که نیازی نیست تا قطعه کد جدید را به صورت SyntaxTrees در آورد و به کامپایلر اضافه کرد. میتوان این قطعه کد را به نحو متداولی، به صورت یک قطعه رشتهی استاندارد #C، تولید و به کامپایلر با متد context.AddSource ارائه کرد که نمونهای از آنرا در ذیل مشاهده میکنید:
در اینجا در ابتدا بدنهی کلاس partial تکمیل میشود. سپس خواص عمومی آن بر اساس فیلدهای خصوصی تعریف شده، تکمیل میشوند. در این مثال اگر یک فیلد خصوصی به عبارت BackingField ختم شود، به عنوان فیلدی که قرار است معادل کدهای INotifyPropertyChanged را داشته باشد، شناسایی میشود و به همراه کدهای تولید شدهی خودکار خواهد بود.
کدهای source generator ما همین مقدار بیشتر نیست. اکنون میخواهیم از آن در یک برنامهی کنسول جدید (برای مثال به نام NotifyPropertyChangedGenerator.Demo) استفاده کنیم. برای اینکار نیاز است ارجاعی را به آن اضافه کنیم؛ اما این ارجاع، یک ارجاع متداول نیست و نیاز به ذکر چنین ویژگی خاصی وجود دارد:
در اینجا میسر دهی پروژهی تولید کنندهی کد، همانند سایر پروژهها است؛ اما نوع آن باید آنالایزر معرفی شود. به همین جهت از خاصیت OutputItemType با مقدار Analyzer استفاده شدهاست. همچنین تنظیم ReferenceOutputAssembly به false به این معنا است که این اسمبلی ویژه، یک وابستگی و dependency واقعی پروژهی جاری نیست و ما قرار نیست به صورت مستقیمی از کدهای آن استفاده کنیم.
برای آزمایش این تولید کنندهی کد، کلاس CarModel را به صورت زیر به پروژهی کنسول آزمایشی اضافه میکنیم:
این کلاس پیاده سازی کنندهی INotifyPropertyChanged است؛ اما به همراه هیچ خاصیت عمومی نیست. فقط به همراه یکسری فیلد خصوصی ختم شدهی به «BackingField» است که توسط تولید کنندهی کد شناسایی شده و اطلاعات آنها تکمیل میشود. فقط باید دقت داشت که این کلاس حتما باید به صورت partial تعریف شود تا امکان تکمیل خودکار کدهای آن وجود داشته باشد.
نحوهی مشاهدهی کدهای خودکار تولید شده
اگر علاقمند باشید تا کدهای خودکار تولید شده را مشاهده کنید، در Visual Studio، در قسمت و درخت نمایشی dependencies پروژه، گرهای به نام Analyzers وجود دارد که در آن برای مثال نام NotifyPropertyChangedGenerator و ذیل آن، کلاسهای تولید شدهی توسط آن، قابل مشاهده و دسترسی هستند و حتی قابل دیباگ نیز میباشند؛ یعنی میتوان بر روی سطور مختلف آن، break-point قرار داد.
هدف از اینترفیس INotifyPropertyChanged که به همراه یک رخداد است:
public interface INotifyPropertyChanged { event PropertyChangedEventHandler PropertyChanged; }
partial class CarModel : INotifyPropertyChanged { private double _speedKmPerHour; public double SpeedKmPerHour { get => _speedKmPerHour; set { _speedKmPerHour = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SpeedKmPerHour))); } } public event PropertyChangedEventHandler? PropertyChanged; }
اگر بخواهیم تولید این کدهای تکراری را به Source Generators محول کنیم، میتوان برای مثال فیلد خصوصی مرتبط را نگه داشت و تولید مابقی کدها را خودکار کرد:
partial class CarModel : INotifyPropertyChanged { private double _speedKmPerHour; }
ایجاد پروژهی Source Generator
در ابتدا برای ایجاد تولید کنندهی خودکار کدهای INotifyPropertyChanged، یک class library را به solution جاری اضافه میکنیم. سپس نیاز است ارجاعاتی را به دو بستهی نیوگت زیر نیز افزود:
<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.2.0" PrivateAssets="all" /> </ItemGroup> </Project>
[Generator] public class NotifyPropertyChangedGenerator : ISourceGenerator { public void Initialize(GeneratorInitializationContext context) { } public void Execute(GeneratorExecutionContext context) {
- اینترفیس ISourceGenerator به همراه دو متد Initialize و Execute است که در صورت نیاز باید پیاده سازی شوند.
در متد Execute، به خاصیت context.Compilation دسترسی داریم. این خاصیت تمام اطلاعاتی را که کامپایلر از Solution جاری در اختیار دارد، به توسعه دهنده ارائه میدهد. برای نمونه پیاده سازی متد Execute تولید کنندهی کد مثال جاری، چنین شکلی را دارد:
public void Execute(GeneratorExecutionContext context) { // uncomment to debug the actual build of the target project // Debugger.Launch(); var compilation = context.Compilation; var notifyInterface = compilation.GetTypeByMetadataName("System.ComponentModel.INotifyPropertyChanged"); foreach (var syntaxTree in compilation.SyntaxTrees) { var semanticModel = compilation.GetSemanticModel(syntaxTree); var immutableHashSet = syntaxTree.GetRoot() .DescendantNodesAndSelf() .OfType<ClassDeclarationSyntax>() .Select(x => semanticModel.GetDeclaredSymbol(x)) .OfType<ITypeSymbol>() .Where(x => x.Interfaces.Contains(notifyInterface)) .ToImmutableHashSet(); foreach (var typeSymbol in immutableHashSet) { var source = GeneratePropertyChanged(typeSymbol); context.AddSource($"{typeSymbol.Name}.Notify.cs", source); } } }
نکتهی مهم و جالب در اینجا این است که نیازی نیست تا قطعه کد جدید را به صورت SyntaxTrees در آورد و به کامپایلر اضافه کرد. میتوان این قطعه کد را به نحو متداولی، به صورت یک قطعه رشتهی استاندارد #C، تولید و به کامپایلر با متد context.AddSource ارائه کرد که نمونهای از آنرا در ذیل مشاهده میکنید:
private string GeneratePropertyChanged(ITypeSymbol typeSymbol) { return $@" using System.ComponentModel; namespace {typeSymbol.ContainingNamespace} {{ partial class {typeSymbol.Name} {{ {GenerateProperties(typeSymbol)} public event PropertyChangedEventHandler? PropertyChanged; }} }}"; } private static string GenerateProperties(ITypeSymbol typeSymbol) { var sb = new StringBuilder(); var suffix = "BackingField"; foreach (var fieldSymbol in typeSymbol.GetMembers().OfType<IFieldSymbol>() .Where(x=>x.Name.EndsWith(suffix))) { var propertyName = fieldSymbol.Name[..^suffix.Length]; sb.AppendLine($@" public {fieldSymbol.Type} {propertyName} {{ get => {fieldSymbol.Name}; set {{ {fieldSymbol.Name} = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof({propertyName}))); }} }}"); } return sb.ToString(); }
کدهای source generator ما همین مقدار بیشتر نیست. اکنون میخواهیم از آن در یک برنامهی کنسول جدید (برای مثال به نام NotifyPropertyChangedGenerator.Demo) استفاده کنیم. برای اینکار نیاز است ارجاعی را به آن اضافه کنیم؛ اما این ارجاع، یک ارجاع متداول نیست و نیاز به ذکر چنین ویژگی خاصی وجود دارد:
<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <ProjectReference Include="..\NotifyPropertyChangedGenerator\NotifyPropertyChangedGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/> </ItemGroup> </Project>
برای آزمایش این تولید کنندهی کد، کلاس CarModel را به صورت زیر به پروژهی کنسول آزمایشی اضافه میکنیم:
using System.ComponentModel; namespace NotifyPropertyChangedGenerator.Demo { public partial class CarModel : INotifyPropertyChanged { private double SpeedKmPerHourBackingField; private int NumberOfDoorsBackingField; private string ModelBackingField = ""; public void SpeedUp() => SpeedKmPerHour *= 1.1; } }
یک نکته: در این حالت هرچند برنامه بدون مشکل کامپایل و اجرا میشود، ممکن است خطوط قرمزی را در IDE خود مشاهده کنید که عنوان میکند این قطعه از کد قابل کامپایل نیست. اگر با چنین صحنهای مواجه شدید، یکبار solution را بسته و مجددا باز کنید تا تولید کنندهی کد، به خوبی شناسایی شود. البته نگارشهای جدیدتر Visual Studio و Rider به همراه قابلیت auto reload پروژه برای کار با تولید کنندههای کد هستند و دیگر شاهد چنین صحنههایی نیستیم و حتی اگر برای مثال فیلد جدیدی را به CarModel اضافه کنیم، نه فقط بلافاصله کدهای متناظر آن تولید میشوند، بلکه خواص عمومی تولید شده در Intellisense نیز قابل دسترسی هستند.
نحوهی مشاهدهی کدهای خودکار تولید شده
اگر علاقمند باشید تا کدهای خودکار تولید شده را مشاهده کنید، در Visual Studio، در قسمت و درخت نمایشی dependencies پروژه، گرهای به نام Analyzers وجود دارد که در آن برای مثال نام NotifyPropertyChangedGenerator و ذیل آن، کلاسهای تولید شدهی توسط آن، قابل مشاهده و دسترسی هستند و حتی قابل دیباگ نیز میباشند؛ یعنی میتوان بر روی سطور مختلف آن، break-point قرار داد.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: SourceGeneratorTests.zip
معرفی تعدادی منبع تکمیلی
- برنامه Source generator playground
در اینجا تعدادی مثال را که توسط مایکروسافت توسعه یافتهاست، مشاهده میکنید که اتفاقا یکی از آنها پیاده سازی تولید کنندهی کد اینترفیس INotifyPropertyChanged است. در این برنامه، خروجی کدهای تولیدی نیز به سادگی قابل مشاهدهاست.
- برنامه SharpLab
برای توسعهی تولید کنندههای کد، عموما نیاز است تا با Roslyn API آشنا بود. در این برنامه اگر از منوی بالای صفحه قسمت results، گزینهی «syntax tree» را انتخاب کنید و سپس قسمتی از کد خود را انتخاب کنید، بلافاصله معادل Roslyn API آن، در سمت راست صفحه نمایش داده میشود.
- معرفی مجموعهای از Source Generators
در اینجا میتوان مجموعهای از پروژههای سورس باز Source Generators را مشاهده و کدهای آنها را مطالعه کنید و یا از آنها در پروژههای خود استفاده نمائید.
- معرفی یک cookbook در مورد Source Generators
این cookbook توسط خود مایکروسافت تهیه شدهاست و جهت شروع به کار با این فناوری، بسیار مفید است.
- مجموعه مثالهای Source generators از مایکروسافت
در اینجا میتوانید مجموعه مثالهایی از Source generators را که توسط مایکروسافت تهیه شدهاست، مشاهده کنید. شرح و توضیحات تعدادی از آنها را هم در اینجا مطالعه کنید.
در اینجا تعدادی مثال را که توسط مایکروسافت توسعه یافتهاست، مشاهده میکنید که اتفاقا یکی از آنها پیاده سازی تولید کنندهی کد اینترفیس INotifyPropertyChanged است. در این برنامه، خروجی کدهای تولیدی نیز به سادگی قابل مشاهدهاست.
- برنامه SharpLab
برای توسعهی تولید کنندههای کد، عموما نیاز است تا با Roslyn API آشنا بود. در این برنامه اگر از منوی بالای صفحه قسمت results، گزینهی «syntax tree» را انتخاب کنید و سپس قسمتی از کد خود را انتخاب کنید، بلافاصله معادل Roslyn API آن، در سمت راست صفحه نمایش داده میشود.
- معرفی مجموعهای از Source Generators
در اینجا میتوان مجموعهای از پروژههای سورس باز Source Generators را مشاهده و کدهای آنها را مطالعه کنید و یا از آنها در پروژههای خود استفاده نمائید.
- معرفی یک cookbook در مورد Source Generators
این cookbook توسط خود مایکروسافت تهیه شدهاست و جهت شروع به کار با این فناوری، بسیار مفید است.
- مجموعه مثالهای Source generators از مایکروسافت
در اینجا میتوانید مجموعه مثالهایی از Source generators را که توسط مایکروسافت تهیه شدهاست، مشاهده کنید. شرح و توضیحات تعدادی از آنها را هم در اینجا مطالعه کنید.
نظرات مطالب
متدهای الحاقی - Extension Methods
سلام، توضیحات آقای نصیری کامل بود. همچنین اضافه کنم که دسترسی به سورس برنامه از طریق این لینک + نیز میسر است.
نظرات مطالب
معماری لایه بندی نرم افزار #3
لطفا دمو یا سورس برنامه رو هم قرار بدید که یادگیری و آموزش سریعتر انجام بشه.
ممنون
ممنون