یک HTML builder مخصوص بوت استرپ
در ابتدا نیاز است که بستههای زیر را از Nuget دریافت و نصب کنیم:
PM>Install-Package Autofac PM>Install-Package Autofac.Mvc5 PM>Install-Package AutoMapper
حال در این بخش به تعاریف داخلی پروژه میپردازیم:
namespace AufacDI.DomainClasses { public class Category { public int Id { get; set; } public string Name { get; set; } } }
namespace AufacDI.ViewModel { public class CategoryViewModel { public int Id { get; set; } public int Name { get; set; } } }
using AufacDI.DomainClasses; using AufacDI.ViewModel; using AutoMapper; namespace AufacDI.MapperProfile { public class CategoryProfile : Profile { public CategoryProfile() { CreateMap<Category, CategoryViewModel>(); CreateMap<CategoryViewModel, Category>(); } } }
using AufacDI.MapperProfile; using Autofac; using AutoMapper; using System; using System.Linq; namespace AufacDI.IocConfig { public static class IoCContainer { public static void Register(ContainerBuilder builder) { // شناسایی پروفایلها براساس نمونه از کلاس پر.وفایل var profiles = from types in typeof(CategoryProfile).Assembly.GetTypes() where typeof(Profile).IsAssignableFrom(types) select (Profile)Activator.CreateInstance(types); // رجیستر کردن کلاسهای پروفایل در اتومپر builder.Register(ctx => new MapperConfiguration(cfg => { foreach (var profile in profiles) cfg.AddProfile(profile); })).SingleInstance().AutoActivate().AsSelf(); // رجیستر کردن کلاس MapperConfiguration و ایجاد آن براساس IMapper builder.Register(ctx => ctx.Resolve<MapperConfiguration>().CreateMapper()).As<IMapper>().InstancePerRequest(); } } }
var builder = new ContainerBuilder(); // تزریق کنترلرها برای تزریف سایر المانها در سازنده builder.RegisterControllers(typeof(MvcApplication).Assembly).InstancePerDependency(); // فراخوانی متد رجیستر برای تزریق وابستگی مپر و کلاسهای پروفایل آن IoCContainer.Register(builder); // ایجاد نمونه از سازنده var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
namespace AufacDI.WebApplication.Controllers { public class HomeController : Controller { private readonly IMapper _mapepr; public HomeController(IMapper mapepr) { _mapepr = mapepr; } public ActionResult Index() { // مپ کردن یک کلاس به یک کلاس var categoryViewModel = new CategoryViewModel { Id = 1, Name = "News" }; var categoryModel = _mapepr.Map<CategoryViewModel, Category>(categoryViewModel); // مپ کردن لیست از کلاس به لیستی از کلاس var categoryListModel = new List<Category>(); categoryListModel.Add(new Category { Id = 1, Name = "A" }); categoryListModel.Add(new Category { Id = 2, Name = "B" }); categoryListModel.Add(new Category { Id = 3, Name = "C" }); categoryListModel.Add(new Category { Id = 4, Name = "D" }); categoryListModel.Add(new Category { Id = 5, Name = "E" }); var categoryListViewModel = categoryListModel.AsQueryable().ProjectTo<CategoryViewModel>(_mapepr.ConfigurationProvider).ToList(); ; return View(); } } }
همیشه در حین توسعهی یک برنامه این سؤالات وجود دارند:
- چند درصد از برنامه تست شده است؟
- برای چه تعدادی از متدهای موجود آزمون واحد نوشتهایم؟
- آیا همین آزمونهای واحد نوشته شده و موجود، کامل هستند و تمام عملکردهای متدهای مرتبط را پوشش میدهند؟
این سؤالات به صورت خلاصه مفهوم Code coverage را در بحث Unit testing ارائه میدهند: برای چه قسمتهایی از برنامه آزمون واحد ننوشتهایم و میزان پوشش برنامه توسط آزمونهای واحد موجود تا چه حدی است؟
بررسی این سؤالات در یک پروژهی کم حجم، ساده بوده و به صورت بازبینی بصری ممکن است. اما در یک پروژهی بزرگ نیاز به ابزار دارد. به همین منظور تعدادی برنامه جهت بررسی code coverage مختص پروژههای دات نتی تابحال تولید شدهاند که در ادامه لیست آنها را مشاهده میکنید:
و ...
تمام اینها تجاری هستند. اما در این بین برنامهی PartCover سورس باز و رایگان بوده و همچنین مختص به NUnit نیز تهیه شده است. این برنامه را از اینجا میتوانید دریافت و نصب کنید. در ادامه نحوهی تنظیم آنرا بررسی خواهیم کرد:
الف) ایجاد یک پروژه آزمون واحد جدید
جهت توضیح بهتر سه سؤال مطرح شده در ابتدای این مطلب، بهتر است یک مثال ساده را در این زمینه مرور نمائیم: (پیشنیاز: (+))
یک Solution جدید در VS.NET آغاز شده و سپس دو پروژه جدید از نوعهای کنسول و Class library به آن اضافه شدهاند:
پروژه کنسول، برنامه اصلی است و در پروژه Class library ، آزمونهای واحد برنامه را خواهیم نوشت.
کلاس اصلی برنامه کنسول به شرح زیر است:
namespace TestPartCover
{
public class Foo
{
public int DoFoo(int x, int y)
{
int z = 0;
if ((x > 0) && (y > 0))
{
z = x;
}
return z;
}
public int DoSum(int x)
{
return ++x;
}
}
}
using NUnit.Framework;
namespace TestPartCover.Tests
{
[TestFixture]
public class Tests
{
[Test]
public void TestDoFoo()
{
var result = new Foo().DoFoo(-1, 2);
Assert.That(result == 0);
}
}
}
به نظر همه چیز خوب است! اما آیا واقعا این آزمون کافی است؟!
ب) در ادامه به کمک برنامهی PartCover میخواهیم بررسی کنیم میزان پوشش آزمونهای واحد نوشته شده تا چه حدی است؟
پس از نصب برنامه، فایل PartCover.Browser.exe را اجرا کرده و سپس از منوی فایل، گزینهی Run Target را انتخاب کنید تا صفحهی زیر ظاهر شود:
توضیحات:
در قسمت executable file آدرس فایل nunit-console.exe را وارد کنید. این برنامه چون در حال حاضر برای دات نت 2 کامپایل شده امکان بارگذاری dll های دات نت 4 را ندارد. به همین منظور فایل nunit-console.exe.config را باز کرده و تنظیمات زیر را به آن اعمال کنید (مهم!):
<configuration>
<startup>
<supportedRuntime version="v4.0.30319" />
</startup>
و همچنین
<runtime>
<loadFromRemoteSources enabled="true" />
در ادامه مقابل working directory ، آدرس پوشه bin پروژه unit test را تنظیم کنید.
در این حالت working arguments به صورت زیر خواهند بود (در غیراینصورت باید مسیر کامل را وارد نمائید):
TestPartCover.Tests.dll /framework=4.0.30319 /noshadow
نام dll وارد شده همان فایل class library تولیدی است. آرگومان بعدی مشخص میکند که قصد داریم یک پروژهی دات نت 4 را توسط NUnit بررسی کنیم (اگر ذکر نشود پیش فرض آن دات نت 2 خواهد بود و نمیتواند اسمبلیهای دات نت 4 را بارگذاری کند). منظور از noshadow این است که NUnit مجاز به تولید shadow copies از اسمبلیهای مورد آزمایش نیست. به این صورت برنامهی PartCover میتواند بر اساس StackTrace نهایی، سورس متناظر با قسمتهای مختلف را نمایش دهد.
اکنون نوبت به تنظیم Rules آن است که یک سری RegEx هستند؛ به عبارتی چه اسمبلیهایی آزمایش شوند و کدامها خیر:
+[TestPartCover]*
-[nunit*]*
-[log4net*]*
همانطور که ملاحظه میکنید در اینجا از اسمبلیهای NUnit و log4net صرفنظر شده است و تنها اسمبلی TestPartCover (همان برنامه کنسول، نه اسمبلی برنامه آزمون واحد) بررسی خواهد گردید.
اکنون بر روی دکمه Save در این صفحه کلیک کرده و فایل نهایی را ذخیره کنید (بعدا توسط دکمه Load در همین صفحه قابل بارگذاری خواهد بود). حاصل باید به صورت زیر باشد:
<PartCoverSettings>
<Target>D:\Prog\Libs\NUnit\bin\net-2.0\nunit-console.exe</Target>
<TargetWorkDir>D:\Prog\1390\TestPartCover\TestPartCover.Tests\bin\Debug</TargetWorkDir>
<TargetArgs>TestPartCover.Tests.dll /framework=4.0.30319 /noshadow</TargetArgs>
<Rule>+[TestPartCover]*</Rule>
<Rule>-[nunit*]*</Rule>
<Rule>-[log4net*]*</Rule>
</PartCoverSettings>
برای شروع به بررسی، بر روی دکمه Start کلیک نمائید. پس از مدتی، نتیجه به صورت زیر خواهد بود:
بله! آزمون واحد تهیه شده تنها 39 درصد اسمبلی TestPartCover را پوشش داده است. مواردی که با صفر درصد مشخص شدهاند، یعنی فاقد آزمون واحد هستند و نکته مهمتر پوشش 91 درصدی متد DoFoo است. برای اینکه علت را مشاهده کنید از منوی View ، گزینهی Coverage detail را انتخاب کنید تا تصویر زیر نمایان شود:
قسمت نارنجی در اینجا به معنای عدم پوشش آن در متد TestDoFoo تهیه شده است. تنها قسمتهای سبز را توانستهایم پوشش دهیم و برای بررسی تمام شرطهای این متد نیاز به آزمونهای واحد بیشتری میباشد.
روش نهایی کار نیز به همین صورت است. ابتدا آزمون واحد تهیه میشود. سپس میزان پوشش آن بررسی شده و در ادامه سعی خواهیم کرد تا این درصد را افزایش دهیم.
نکته: آشنایی اولیه با مفاهیم MEF از ملزومات این بخش است.
»ابتدا یک Class Library به نام Views ایجاد نمایید و اینترفیس زیر را به صورت زیر در آن تعریف نمایید. این اینترفیس رابط بین کنترلر و View از طریق ViewModel خواهد بود.
public interface IBookView : IView { void Show(); void Close(); }
Install-Package WAF
<Window x:Class="Shell.BookShell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Book View" Height="350" Width="525"> <Grid> <DataGrid ItemsSource="{Binding Books}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="400" Height="200"> <DataGrid.Columns> <DataGridTextColumn Header="Code" Binding="{Binding Code}" Width="100"></DataGridTextColumn> <DataGridTextColumn Header="Title" Binding="{Binding Title}" Width="300"></DataGridTextColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
[Export(typeof(IBookView))] [PartCreationPolicy(CreationPolicy.NonShared)] public partial class BookShell : Window, IBookView { public BookShell() { InitializeComponent(); } }
»یک Class Library به نام Models بسازید و بعد از ایجاد آن، کلاس زیر را به عنوان مدل Book در آن کپی کنید:
public class Book { public int Code { get; set; } public string Title { get; set; } }
[Export] [Export(typeof(ViewModel<IBookView>))] public class BookViewModel : ViewModel<IBookView> { [ImportingConstructor] public BookViewModel(IBookView view) : base(view) { } public ObservableCollection<Book> Books { get; set; } }
به دلیل اینکه سازنده پیش فرض در این کلاس وجود ندارد حتما باید از ImportingConstructor استفاده نماییم تا CompositionContainer در هنگام عملیات وهله سازی Exception صادر نکند.
»بخش بعدی ساخت یک Class Library دیگر به نام Controllers است. در این Library نیز بعد از ارجاع به اسمبلیهای زیر کتابخانه WAF را نصب نمایید.
- Views
- Models
- ViewModels
- System.ComponentModel.Composition
[Export] public class BookController { [ImportingConstructor] public BookController(BookViewModel viewModel) { ViewModelCore = viewModel; } public BookViewModel ViewModelCore { get; private set; } public void Run() { var result = new List<Book>(); result.Add(new Book { Code = 1, Title = "Book1" }); result.Add(new Book { Code = 2, Title = "Book2" }); result.Add(new Book { Code = 3, Title = "Book3" }); ViewModelCore.Books = new ObservableCollection<Models.Book>(result); (ViewModelCore.View as IBookView).Show(); } }
طراحی Bootstrapper
در پروژههای ماژولار Bootstrapper از ملزومات جدانشدنی این گونه پروژه هاست. برای این کار ابتدا یک WPF Application دیگر به نام Bootstrapper ایجاد نماید. سپس ارجاعی به اسمبلیهای زیر را در آن قرار دهید:
»Controllers
»Views
»ViewModels
»Shell
»System.ComponentModel.Composition
»نصب بسته WAF با استفاده از nuget
حال یک کلاس به نام AppBootstrapper ایجاد نمایید و کدهای زیر را در آن کپی نمایید:
public class AppBootstrapper { public CompositionContainer Container { get; private set; } public AggregateCatalog Catalog { get; private set; } public void Run() { Catalog = new AggregateCatalog(); Catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "Shell.dll"))); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "ViewModels.dll"))); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "Controllers.dll"))); Container = new CompositionContainer(Catalog); var batch = new CompositionBatch(); batch.AddExportedValue(Container); Container.Compose(batch); var bookController = Container.GetExportedValue<BookController>(); bookController.Run(); } }
نکته بخش Startup را از فایل App.Xaml خذف نمایید و در متد Startup این فایل کد زیر را کپی کنید:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { new Bootstrapper.AppBootstrapper().Run(); } }
نکته: میتوان بخش اسکن اسمبلیها را توسط یک DirecotryCatalog به صورت زیر خلاصه کرد:
Catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
نکته: میتوان به جای جداسازی فیزیکی لایهها آنها را از طریق Directoryها به صورت منطقی در قالب یک اسمبلی نیز مدیریت کرد.
نکته: بهتر است به جای رفرنس مستقیم اسمبلیها به Bootstrapper با استفاده از Pre post build در قسمت Build Event، اسمبلیهای مورد نظر را در یک مسیر Build کپی نمایید که روش آن به تفصیل در این پست و این پست شرح داده شده است.
دانلود سورس پروژه
<div id="s4-ribbonrow">
<Sharepoint:SPSecurityTrimmedControl runat="server" Permissions="AddDelPrivateWebParts">
و تگ پایانی آن :
نکته مهم در استفاده از این تگ ، ویژگی Permissions آن است که باید با دقت و بسته به نیاز شما تعریف شود :
برخی از این موارد عبارتند از :
EmptyMask – Has no permissions on the Web site. Not available through the user interface.
ViewListItems – View items in lists, documents in document libraries, and view Web discussion comments.
AddListItems – Add items to lists, add documents to document libraries, and add Web discussion comments.
EditListItems – Edit items in lists, edit documents in document libraries, edit Web discussion comments in documents, and customize Web Part Pages in document libraries.
DeleteListItems – Delete items from a list, documents from a document library, and Web discussion comments in documents.
ApproveItems – Approve a minor version of a list item or document.
OpenItems – View the source of documents with server-side file handlers.
ViewVersions – View past versions of a list item or document.
DeleteVersions – Delete past versions of a list item or document.
CancelCheckout – Discard or check in a document which is checked out to another user.
ManagePersonalViews – Create, change, and delete personal views of lists.
ManageLists – Create and delete lists, add or remove columns in a list, and add or remove public views of a list.
ViewFormPages – View forms, views, and application pages, and enumerate lists.
Open – Allow users to open a Web site, list, or folder to access items inside that container.
ViewPages – View pages in a Web site.
AddAndCustomizePages – Add, change, or delete HTML pages or Web Part Pages, and edit the Web site using a SharePoint Foundation–compatible editor.
ApplyThemeAndBorder – Apply a theme or borders to the entire Web site.
ApplyStyleSheets – Apply a style sheet (.css file) to the Web site.
ViewUsageData – View reports on Web site usage.
CreateSSCSite – Create a Web site using Self-Service Site Creation.
ManageSubwebs – Create subsites such as team sites, Meeting Workspace sites, and Document Workspace sites.
CreateGroups – Create a group of users that can be used anywhere within the site collection.
ManagePermissions – Create and change permission levels on the Web site and assign permissions to users and groups.
BrowseDirectories – Enumerate files and folders in a Web site using Microsoft Office SharePoint Designer 2007 and WebDAV interfaces.
BrowseUserInfo – View information about users of the Web site.
AddDelPrivateWebParts – Add or remove personal Web Parts on a Web Part Page.
UpdatePersonalWebParts – Update Web Parts to display personalized information.
ManageWeb – Grant the ability to perform all administration tasks for the Web site as well as manage content. Activate, deactivate, or edit properties of Web site scoped Features through the object model or through the user interface (UI). When granted on the root Web site of a site collection, activate, deactivate, or edit properties of site collection scoped Features through the object model. To browse to the Site Collection Features page and activate or deactivate site collection scoped Features through the UI, you must be a site collection administrator.
UseClientIntegration – Use features that launch client applications; otherwise, users must work on documents locally and upload changes.
UseRemoteAPIs – Use SOAP, WebDAV, or Microsoft Office SharePoint Designer 2007 interfaces to access the Web site.
ManageAlerts – Manage alerts for all users of the Web site.
CreateAlerts – Create e-mail alerts.
EditMyUserInfo – Allows a user to change his or her user information, such as adding a picture.
EnumeratePermissions – Enumerate permissions on the Web site, list, folder, document, or list item.
FullMask – Has all permissions on the Web site. Not available through the user interface.
حال خارج از تگهای SPSecurityTrimmedControl در ابتدا یا انتها ، باید تگ login را مانند زیر به آن اضافه کرد .
و تمام :
مسیر راه ASP.NET Core 2.1
The following high-level features are planned for the ASP.NET Core 2.1 release:
SignalR - Real-time web framework on ASP.NET Core (aspnet/SignalR#394)
HTTPS - On by default and easy to configure (aspnet/Home#2308)
GDPR compliance - Templates updated with new privacy features (aspnet/Security#1561, aspnet/Identity#1341)
Web API conventions - Rich Swagger support without attributes (aspnet/Mvc#6870, aspnet/Mvc#6784)
IHttpClientFactory - HttpClient as a service, handle cross-cutting concerns like caching, retry logic, timeouts and circuit breakers (aspnet/HttpClientFactory#42)
ASP.NET Core Module in-proc hosting - 6x the throughput on IIS! Better startup error handling (aspnet/AspNetCoreModule#265)
Razor pages improvements - Support for areas, ~/Pages/Shared (aspnet/Mvc#6926, aspnet/Mvc#7193)
MVC functional test fixture - Easily test your MVC apps end-to-end (aspnet/Mvc#6233)
Build-time Razor - Compile Razor pages and views as part of your build, improved startup performance (aspnet/Razor#1809)
UI as a library - Package Razor pages and views as reusable libraries (aspnet/Razor#1809)
Identity UI package and scaffolder - Add identity to any application (aspnet/Home#2311)
WebHooks - Handle WebHook notifications from ASP.NET Core apps (aspnet/WebHooks#5)
- Kernel
- ماشین مجازی Dalvik
- application framework
- applications
هسته اندروید (kernel) چیست؟
اندروید بر روی هسته لینوکس نسخه 2.6 به بالاتر اجرا میشود. هسته، اولین و نخستین لایهی نرم افزاری در اندروید است که با سخت افزار به صورت کاملا مستقیم در تعامل میباشد. تغییرات در هسته و یا ساختن دوبارهی آن چیزی نیست که لازم باشد از ابتدا به ساکن و مجددا توسط یک برنامه نویس انجام شود! فقط سازندگان سخت افزار قادر به تغییرات درون هسته هستند و این یک امر غیرطبیعی و ناممکن برای برنامه نویسان خواهد بود؛ چرا که یک برنامه نویس تنها قادر است تا لایههای نرم افزاری را تغییر دهد نه سخت افزار آن را و این مورد تنها بهعهدهی افرادی است که با سخت افزار اندروید در ارتباط هستند.
کتابخانه ها
اجزای کتابخانهها بعنوان یک لایه مترجم بین هسته و فریم ورکها عمل میکنند. این کتابخانهها و اجزای درونی آنها با زبان C و ++C نوشته شدهاند؛ اما از طریق یک API در زبان جاوا در اختیار توسعه دهندگان قرار میگیرند تا به سهولت قابل استفاده باشند. برنامه نویسان و توسعه دهندگان میتوانند از طریق فریم ورکهای زبان جاوا برای دسترسی مستقیم به کتابخانههای اصلی C و ++C استفاده کنند.
برخی از کتابخانههای اصلی عبارتند از:
- LibWebCore
- Media libraries
- Graphics libraries
ماشین مجازی Dalvik چیست؟
در اصل آقای Dan Bornstein ماشین مجازی Dalvik را نوشت. ماشین مجازی دالویک برای اجرای برنامهها بر روی دستگاههای مختلف با منابع بسیار محدود نوشته شده بود و این یکی از اولویتهای این ماشین بود تا بتواند با منابع محدود بر روی دستگاه در تعامل باشد و برنامه را اجرا نماید. به طور معمول ماشین دالویک برای تلفنهای همراهای استفاده میشد که توان پردازشی پایین، عمر باتری کم و همچنین حافظهی اندکی داشتند. ماشین مجازی دالویک فایلهای با پسوند dex. را اجرا میکند. این فایلها با استفاده از کلاسهای جاوا کامپایل شدهاند که با در نظر گرفتن نوع کلاس class. یا jar. انجام میشوند و فایلهای class. را به یک ثابت (constant) مشترک و هماهنگ تبدیل مینمایند. ابزار DX، که در Android SDK موجود است، این تبدیل را انجام میدهد.
به تصویر زیر توجه کنید:
به تصویر زیر توجه کنید؛ پس از تبدیل، فایلهای dex. به طرز قابل توجهی کوچکتر و کم حجمتر میشوند!
Application Framework چیست؟
اپلیکیشن فریم ورک، یکی از بلاکهای مهم ساختن سیستم نهایی میباشد. این فریم ورکها مجموعهای از خدمات را درون سیستم برای برنامهنویس یا توسعه دهندگان جهت نوشتن یک برنامه بدون مشکل فراهم میکنند. بهعنوان یک توسعه دهنده شما کد را مینویسید و فقط از APIها برای تکمیل آنها در زبان جاوا استفاده میکنید. از طریق یک API در زبان جاوا قادر خواهید بود تا به هسته و کتابخانههای C و ++C دسترسی داشته باشید.
بعنوان نمونه : کد زیر به شما نحوه پخش یک فایل ویدئویی را نشان میدهد
package com.example.android.apis.media; import com.example.android.apis.R; import android.app.Activity; import android.os.Bundle; import android.widget.MediaController; import android.widget.Toast; import android.widget.VideoView; public class VideoViewDemo extends Activity { /** * TODO: Set the path variable to a streaming video URL or a local media * file path. */ private String path = ""; private VideoView mVideoView; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.videoview); mVideoView = (VideoView) findViewById(R.id.surface_view); if (path == "") { // Tell the user to provide a media file URL/path. Toast.makeText( VideoViewDemo.this, "Please edit VideoViewDemo Activity, and set path" + " variable to your media file URL/path", Toast.LENGTH_LONG).show(); } else { /* * Alternatively,for streaming media you can use * mVideoView.setVideoURI(Uri.parse(URLstring)); */ mVideoView.setVideoPath(path); mVideoView.setMediaController(new MediaController(this)); mVideoView.requestFocus(); } } }