«بررسی مفاهیم معکوس سازی وابستگیها و ابزارهای مرتبط با آن»
«اصول طراحی SOLID»
«مطالعهی بیشتر»
تزریق وابستگیها (یا Dependency injection = DI) به معنای ارسال نمونهای/وهلهای از وابستگی (یک سرویس) به شیء وابستهی به آن (یک کلاینت) است. در فرآیند تزریق وابستگیها، یک کلاس، وهلههای کلاسهای دیگر مورد نیاز خودش را بجای وهله سازی مستقیم، از یک تزریق کننده دریافت میکند. بنابراین بجای نوشتن newها در کلاس جاری، آنها را به صورت وابستگیهایی در سازندهی کلاس تعریف میکنیم تا توسط یک IoC Container تامین شوند. در اینجا به فریم ورکهایی که کار وهله سازی این وابستگیها را انجام میدهند، IoC Container و یا DI container میگوییم (IoC = inversion of control ).
چندین نوع تزریق وابستگیها وجود دارند که دو حالت زیر، عمومیترین آنها است:
الف) تزریق در سازندهی کلاس: لیست وابستگیهای یک کلاس، به عنوان پارامترهای سازندهی آن ذکر میشوند.
ب) تزریق در خواص یا Setter injection: کلاینت خواصی get و set را به صورت public معرفی میکند و سپس IoC Container با وهله سازی آنها، وابستگیهای مورد نیاز را تامین خواهد کرد.
تزریق وابستگیها در ASP.NET Core
برخلاف نگارشهای قبلی ASP.NET، این نگارش جدید از ابتدا با دید پشتیبانی کامل از DI طراحی شدهاست و این مفهوم، در سراسر اجزای آن به صورت یکپارچهای پشتیبانی میشود. همچنین به همراه یک minimalistic DI container توکار نیز هست .
این IoC Container توکار از 4 حالت طول عمر ذیل پشتیبانی میکند:
- instance: در هربار نیاز به یک وابستگی خاص، تنها یک وهله از آن در اختیار مصرف کننده قرار میگیرد و در اینجا شما هستید که مسئول تعریف نحوهی وهله سازی این شیء خواهید بود (برای بار اول).
- transient: هربار که نیاز به وابستگی خاصی بود، یک وهلهی جدید از آن توسط IoC Container تولید و ارائه میشود.
- singleton: در این حالت تنها یک وهله از وابستگی درخواست شده در طول عمر برنامه تامین میشود.
- scoped: در طول عمر یک scope خاص، تنها یک وهله از وابستگی درخواست شده، در اختیار مصرف کنندهها قرار میگیرد. برای مثال مرسوم است که به ازای یک درخواست وب، تنها یک وهله از شیءایی خاص در اختیار تمام مصرف کنندههای آن قرار گیرد (single instance per web request).
طول عمر singleton، برای سرویسها و کلاسهای config مناسب هستند. به این ترتیب به کارآیی بالاتری خواهیم رسید و دیگر نیازی نخواهد بود تا هر بار این اطلاعات خوانده شوند. حالت scoped برای وهله سازی الگوی واحد کار و پیاده سازی تراکنشها مناسب است. برای مثال در طی یک درخواست وب، یک تراکنش باید صورت گیرد.
حالت scoped در حقیقت نوع خاصی از حالت transient است. در حالت transient صرفنظر از هر حالتی، هربار که وابستگی ویژهای درخواست شود، یک وهلهی جدید از آن تولید خواهد شد. اما در حالت scoped فقط یک وهلهی از وابستگی مورد نظر، در بین تمام اشیاء وابستهی به آن، در طول عمر آن scope تولید میشود.
بنابراین در برنامههای وب دو نوع singleton برای معرفی کلاسهای config و نوع scoped برای پیاده سازی تراکنشها و همچنین بالابردن کارآیی برنامه در طی یک درخواست وب (با عدم وهله سازی بیش از اندازهی از کلاسهای مختلف مورد نیاز)، بیشتر از همه به کار برده میشوند.
یک مثال کاربردی: بررسی نحوهی تزریق یک سرویس سفارشی به کمک IoC Container توکار ASP.NET Core
مثال جاری که بر اساس ASP.NET Core Web Application و با قالب خالی آن ایجاد شدهاست، دارای نام فرضی Core1RtmEmptyTest است. در همین پروژه بر روی پوشهی src، کلیک راست کرده و گزینهی Add new project را انتخاب کنید و سپس یک پروژهی جدید از نوع NET Core -> Class library. را به آن، با نام Core1RtmEmptyTest.Services اضافه کنید (تصویر فوق).
در ادامه کلاس نمونهی سرویس پیامها را به همراه اینترفیس آن، با محتوای زیر به آن اضافه کنید:
namespace Core1RtmEmptyTest.Services { public interface IMessagesService { string GetSiteName(); } public class MessagesService : IMessagesService { public string GetSiteName() { return "DNT"; } } }
انجام اینکار معادل است با افزودن یک سطر ذیل به فایل project.json پروژه:
{ "dependencies": { // same as before "Core1RtmEmptyTest.Services": "1.0.0-*" },
public void Configure( IApplicationBuilder app, IHostingEnvironment env, IMessagesService messagesService)
public void Configure( IApplicationBuilder app, IHostingEnvironment env, IMessagesService messagesService) { app.Run(async context => { var siteName = messagesService.GetSiteName(); await context.Response.WriteAsync($"Hello {siteName}"); }); }
System.InvalidOperationException No service for type 'Core1RtmEmptyTest.Services.IMessagesService' has been registered. at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder) System.Exception Could not resolve a service of type 'Core1RtmEmptyTest.Services.IMessagesService' for the parameter 'messagesService' of method 'Configure' on type 'Core1RtmEmptyTest.Startup'. at Microsoft.AspNetCore.Hosting.Internal.ConfigureBuilder.Invoke(object instance, IApplicationBuilder builder) at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddTransient<IMessagesService, MessagesService>(); }
پس از اینکار، مجددا برنامه را اجرا کنید. اکنون این خروجی باید مشاهده شود:
و به این معنا است که اکنون IoC Cotanier توکار ASP.NET Core، میداند زمانیکه به IMessagesService رسید، چگونه باید آنرا وهله سازی کند.
چه سرویسهایی به صورت پیش فرض در IoC Container توکار ASP.NET Core ثبت شدهاند؟
در ابتدای متد ConfigureServices یک break point را قرار داده و برنامه را در حالت دیباگ اجرا کنید:
همانطور که ملاحظه میکنید، به صورت پیش فرض 16 سرویس در اینجا ثبت شدهاند که تاکنون با دو مورد از آنها کار کردهایم.
امکان تزریق وابستگیها در همه جا!
در مثال فوق، سرویس سفارشی خود را در متد Configure کلاس آغازین برنامه تزریق کردیم. نکتهی مهم اینجا است که برخلاف نگارشهای قبلی ASP.NET MVC (یعنی بدون نیاز به تنظیمات خاصی برای قسمتهای مختلف برنامه)، میتوان این تزریقها را در کنترلرها، در میان افزارها، در فیلترها در ... همه جا و تمام اجزای ASP.NET Core 1.0 انجام داد و دیگر اینبار نیازی نیست تا نکتهی ویژهی نحوهی تزریق وابستگیها در فیلترها یا کنترلرهای ASP.NET MVC را یافته و سپس اعمال کنید. تمام اینها از روز اول کار میکنند. همینقدر که کار ثبت سرویس خود را در متد ConfigureServices انجام دادید، این سرویس در سراسر اکوسیستم ASP.NET Core، قابل دسترسی است.
نیاز به تعویض IoC Container توکار ASP.NET Core
قابلیت تزریق وابستگیهای توکار ASP.NET Core صرفا جهت برآورده کردن نیازمندیهای اصلی آن طراحی شدهاست و نه بیشتر. بنابراین توسط آن قابلیتهای پیشرفتهای را که سایر IoC Containers ارائه میدهند، نخواهید یافت. برای مثال تعویض امکانات تزریق وابستگیهای توکار ASP.NET Core با StructureMap این مزایا را به همراه خواهد داشت:
• امکان ایجاد child/nested containers (پشتیبانی از سناریوهای چند مستاجری)
• پشتیبانی از Setter Injection
• امکان انتخاب سازندهای خاص (اگر چندین سازنده تعریف شده باشند)
• سیم کشی خودکار یا Conventional "Auto" Registration (برای مثال اتصال اینترفیس IName به کلاس Name به صورت خودکار و کاهش تعداد تعاریف ابتدای برنامه)
• پشتیبانی توکار از Lazy و Func
• امکان وهله سازی از نوعهای concrete (یا همان کلاسهای معمولی)
• پشتیبانی از مفاهیمی مانند Interception و AOP
• امکان اسکن اسمبلیهای مختلف جهت یافتن اینترفیسها و اتصال خودکار آنها (طراحیهای افزونه پذیر)
روش تعویض IoC Container توکار ASP.NET Core با StructureMap
جزئیات این جایگزین کردن را در مطلب «جایگزین کردن StructureMap با سیستم توکار تزریق وابستگیها در ASP.NET Core 1.0» میتوانید مطالعه کنید.
یا میتوانید از روش فوق استفاده کنید و یا اکنون قسمتی از پروژهی رسمی استراکچرمپ در آدرس https://github.com/structuremap/structuremap.dnx جهت کار با NET Core. طراحی شدهاست. برای کار با آن نیاز است این مراحل طی شوند:
الف) دریافت بستهی نیوگت StructureMap.Dnx
برای این منظور بر روی گره references کلیک راست کرده و گزینهی manage nuget packages را انتخاب کنید. سپس در برگهی browse آن، StructureMap.Dnx را جستجو کرده و نصب نمائید (تیک مربوط به انتخاب pre releases هم باید انتخاب شده باشد):
انجام این مراحل معادل هستند با افزودن یک سطر ذیل به فایل project.json برنامه:
{ "dependencies": { // same as before "StructureMap.Dnx": "0.5.1-rc2-final" },
پس از نصب بستهی StructureMap.Dnx، به کلاس آغازین برنامه مراجعه کرده و این تغییرات را اعمال کنید:
public class Startup { public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddDirectoryBrowser(); var container = new Container(); container.Configure(config => { config.Scan(_ => { _.AssemblyContainingType<IMessagesService>(); _.WithDefaultConventions(); }); //config.For<IMessagesService>().Use<MessagesService>(); config.Populate(services); }); container.Populate(services); return container.GetInstance<IServiceProvider>(); }
سپس وهلهای از IServiceProvider، توسط استراکچرمپ تامین شده و بازگشت داده میشود تا بجای IoC Container توکار ASP.NET Core استفاده شود.
در این مثال چون در متد Scan، کار بررسی اسمبلی لایه سرویس برنامه با قراردادهای پیش فرض استراکچرمپ انجام شدهاست، دیگر نیازی به سطر تعریف config.For نیست. در اینجا هرگاه IName ایی یافت شد، به کلاس Name متصل میشود (name هر نامی میتواند باشد).
This post shows how to import and export .xls or .xlsx (Excel files) in ASP.NET Core. And when thinking about dealing with excel with .NET, we always look for third-party libraries or component. And one of the most popular .net library that reads and writes Excel 2007/2010 files using the Open Office Xml format (xlsx) is EPPlus. However, at the time of writing this post, this library is not updated to support .NET Core. But there exists an unofficial version of this library EPPlus.Core which can do the job of import and export xlsx in ASP.NET Core. This works on Windows, Linux and Mac.
A GitHub App that keeps your forks up-to-date with upstream via automated pull requests.
اگه بخواین یه مخزنی که توی گیتهاب Fork کردین رو با سورس اصلی (upstream) بروز رسانی کنین کمی دردسر داره و این کار باید هر بار به صورت دستی انجام بشه
ولی این Github App رایگان اینکار رو بدون هیچ دردسری و به صورت خودکار و مداوم انجام میده براتون.
.NET 8 Preview 4 is now available and includes many great new improvements to ASP.NET Core.
Here’s a summary of what’s new in this preview release:
Blazor
Streaming rendering with Blazor components
Handling form posts with Blazor SSR
Route to named elements in Blazor
Webcil packaging for Blazor WebAssembly apps
API authoring
Expanded support for form binding in minimal APIs
API project template includes .http file
Native AOT
Logging and exception handling in compile-time generated minimal APIs
ASP.NET Core top-level APIs annotated for trim warnings
Reduced app size with configurable HTTPS support
Worker Service template updates
Additional default services configured in the slim builder
API template JSON configuration changes
Support for JSON serialization of compiler-generated IAsyncEnumerable unspeakable types
Authentication and authorization
Identity API endpoints
Improved support for custom authorization policies with IAuthorizationRequirementData
ASP.NET Core metrics
For more details on the ASP.NET Core work planned for .NET 8 see the full ASP.NET Core roadmap for .NET 8 on GitHub.
The Project File Tools Visual Studio extension provides package name and version IntelliSense, tooltips for packages, and more, when editing a .csproj
file in Visual Studio
1. SheetJS
Parser and writer for various spreadsheet formats. Pure-JS cleanroom implementation from official specifications, related documents, and test files. Emphasis on parsing and writing robustness, cross-format feature compatibility with a unified JS representation, and ES3/ES5 browser compatibility back to IE6.
.....