فایلهای کامل بوت استرپ 2 را از طریق دستور ذیل که پیشتر نیز ذکر شده بود دریافت کنید (تمام اجزای js آن با هم یکی شدهاند در قالب یک فایل نهایی):
PM> Install-Package Twitter.BootstrapRTL -Version 2.3.2.1
PM> Install-Package Twitter.BootstrapRTL -Version 2.3.2.1
csc /t:module RUT.cs
csc /out:MultiFileLibrary.dll /t:library /addmodule:RUT.netmodule FUT.cs
File #1 (26000001) Token: 0x26000001 Name : RUT.netmodule HashValue Blob : e6 e6 df 62 2c a1 2c 59 97 65 0f 21 44 10 15 96 f2 7e db c2 Flags : [ContainsMetaData] (00000000) ExportedType #1 (27000001) Token: 0x27000001 Name: ARarelyUsedType Implementation token: 0x26000001 TypeDef token: 0x02000002 Flags : [Public] [AutoLayout] [Class] [Sealed] [AnsiClass] [BeforeFieldInit](00100101)
قابل توجه افراد کنجکاو: توکنهای جداول متا، مقادیر 4 بایتی است که بایت پر ارزش آن اشاره میکند که برای یافتن آن باید به چه جدولی ارجاع کرد. مقادیر زیر این نکته را روشن میکند که هر کد ابتدایی به چه جدولی اشاره میکند:
0x01 | TypeRef |
0x02 | TypeDef |
0x23 | AssemblyRef |
0x26 | File file definition |
0x27 | ExportedType |
برای دیدن لیست کاملی از این کدها فایل Corhdr.h را که به همراه فریم ورک دات نت نصب میشود، مطالعه فرمایید. سه بایت باقیمانده هم بر اساس جدولی که به آن ارجاع شده است مشخص میگردد؛ مثلا در مثال بالا کد 0x26000001 به اولین سطر جدول File اشاره میکند. برای اکثر جدولها شماره گذاری سطرها از عدد 1 آغاز میشود نه صفر یا برای برای جداول TypeDef عموما از عدد 2 آغاز میشود.
برای اجرای اسمبلی، کامپایلر نیاز دارد که همهی فایلهای اسمبلی، نصب شده و قابل دسترس باشند و در صورتیکه شما فایل RUT.netmodule را حذف کنید کامپایلر سی شارپ خطای زیر را صادر میکند:fatal error CS0009: Metadata file 'C:\ MultiFileLibrary.dll' could not be opened—'Error importing module 'RUT.netmodule' of assembly 'C:\ MultiFileLibrary.dll'—The system cannot find the file specified'
PM > Install-Package Microsoft.Xaml.Behaviors.Wpf
private static ObjectQuery TryGetObjectQuery<T>(IQueryable<T> source) { var dbQuery = source as DbQuery<T>; if (dbQuery != null) { const BindingFlags privateFieldFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public; var internalQuery = source.GetType().GetProperty("InternalQuery", privateFieldFlags) .GetValue(source); return (ObjectQuery)internalQuery.GetType().GetProperty("ObjectQuery", privateFieldFlags) .GetValue(internalQuery); } return null; }
PM> Install-Package EFSecondLevelCache
var products = context.Products.Include(x => x.Tags).FirstOrDefault();
var products = context.Products.Include(x => x.Tags).Cacheable().FirstOrDefault(); // Async methods are supported too.
namespace EFSecondLevelCache.TestDataLayer.DataLayer { public class SampleContext : DbContext { // public DbSet<Product> Products { get; set; } public SampleContext() : base("connectionString1") { } public override int SaveChanges() { return SaveAllChanges(invalidateCacheDependencies: true); } public int SaveAllChanges(bool invalidateCacheDependencies = true) { var changedEntityNames = getChangedEntityNames(); var result = base.SaveChanges(); if (invalidateCacheDependencies) { new EFCacheServiceProvider().InvalidateCacheDependencies(changedEntityNames); } return result; } private string[] getChangedEntityNames() { return this.ChangeTracker.Entries() .Where(x => x.State == EntityState.Added || x.State == EntityState.Modified || x.State == EntityState.Deleted) .Select(x => ObjectContext.GetObjectType(x.Entity.GetType()).FullName) .Distinct() .ToArray(); } } }
using System.Data;
using System.IO;
using OfficeOpenXml;
using OfficeOpenXml.Drawing.Chart;
using OfficeOpenXml.Style;
using OfficeOpenXml.Table;
namespace EPPlusTest
{
class Program
{
static void Main(string[] args)
{
var newFile = new FileInfo("Test.xlsx");
if (newFile.Exists)
{
newFile.Delete();
}
//ایجاد یک سری اطلاعات دلخواه
var table = createDt();
using (var package = new ExcelPackage(newFile))
{
// اضافه کردن یک ورک شیت جدید
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("مخارج");
//اضافه کردن یک جدول جدید از دیتاتیبل دریافتی
worksheet.Cells["A1"].LoadFromDataTable(table, true, TableStyles.Dark9);
//نمایش جمع ستون هزینههای ماهها
var tbl = worksheet.Tables[0];
//زیر آخرین ردیف یک سطر اضافه میکند
tbl.ShowTotal = true;
//فرمول نحوهی محاسبه جمع ستون انتساب داده میشود
tbl.Columns[1].TotalsRowFunction = RowFunctions.Sum;
//تعیین عرض ستونهای جدول
worksheet.Column(1).Width = 14;
worksheet.Column(2).Width = 12;
//تنظیم متن هدر
worksheet.HeaderFooter.oddHeader.CenteredText = "مثالی از نحوهی استفاده از ایی پی پلاس";
//میخواهیم سرستونها در وسط ستون قرار گیرند
worksheet.Cells["A1"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
worksheet.Cells["B1"].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
//افزودن یک نمودار جدید به شیت جاری
var chart = worksheet.Drawings.AddChart("chart1", eChartType.Pie3D);
chart.Title.Text = "نمودار هزینههای سال";
chart.SetPosition(Row: 2, RowOffsetPixels: 5, Column: 3, ColumnOffsetPixels: 5);
chart.SetSize(PixelWidth: 320, PixelHeight: 360);
chart.Series.Add("B2:B13", "A2:A13");
chart.Style = eChartStyle.Style26;
//تنظیم یک سری خواص فایل نهایی
package.Workbook.Properties.Title = "مثالی از ایی پی پلاس";
package.Workbook.Properties.Author = "وحید";
package.Workbook.Properties.Subject = "ایجاد فایل اکسل بدون نرم افزار اکسل";
//تنظیم نحوهی نمایش فایل زمانیکه در نرم افزار اکسل گشوده میشود
worksheet.View.PageLayoutView = true;
worksheet.View.RightToLeft = true;
// ذخیر سازی کلیه موارد اعمالی در فایل
package.Save();
}
}
private static DataTable createDt()
{
var table = new DataTable("مخارج");
table.Columns.Add("ماه", typeof(string));
table.Columns.Add("هزینه", typeof(decimal));
table.Rows.Add("فروردین", 100);
table.Rows.Add("اردیبهشت", 250);
table.Rows.Add("خرداد", 80);
table.Rows.Add("تیر", 300);
table.Rows.Add("مرداد", 200);
table.Rows.Add("شهریور", 150);
table.Rows.Add("مهر", 250);
table.Rows.Add("آبان", 200);
table.Rows.Add("آذر", 400);
table.Rows.Add("دی", 100);
table.Rows.Add("بهمن", 130);
table.Rows.Add("اسفند", 80);
return table;
}
}
}
#OS junk files [Tt]humbs.db *.DS_Store #Visual Studio files *.[Oo]bj *.user *.aps *.pch *.vspscc *.vssscc *_i.c *_p.c *.ncb *.suo *.tlb *.tlh *.bak *.[Cc]ache *.ilk *.log *.lib *.sbr *.sdf *.opensdf *.unsuccessfulbuild ipch/ obj/ [Bb]in [Dd]ebug*/ [Rr]elease*/ Ankh.NoLoad #MonoDevelop *.pidb *.userprefs #Tooling _ReSharper*/ *.resharper [Tt]est[Rr]esult* *.sass-cache #Project files [Bb]uild/ #Subversion files .svn # Office Temp Files ~$* #NuGet packages/ #ncrunch *ncrunch* *crunch*.local.xml # visual studio database projects *.dbmdl #Test files *.testsettings
>ng g s employee/FormPoster -m employee.module
installing service create src\app\employee\form-poster.service.spec.ts create src\app\employee\form-poster.service.ts update src\app\employee\employee.module.ts
import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import { Employee } from './employee'; @Injectable() export class FormPosterService { constructor(private http:Http) { } postEmployeeForm(employee: Employee) { } }
import { HttpModule } from "@angular/http"; @NgModule({ imports: [ BrowserModule, FormsModule, HttpModule, EmployeeModule, AppRoutingModule ]
import { FormPosterService } from "../form-poster.service"; export class EmployeeRegisterComponent implements OnInit { constructor(private formPoster: FormPosterService) {} }
>npm install >ng build --watch
>dotnet restore >dotnet watch run
<form #form="ngForm" (submit)="submitForm(form)" novalidate>
export class EmployeeRegisterComponent implements OnInit { submitForm(form: NgForm) { console.log(this.model); console.log(form.value); } }
import { Injectable } from "@angular/core"; import { Http, Response, Headers, RequestOptions } from "@angular/http"; import { Observable } from "rxjs/Observable"; import "rxjs/add/operator/do"; import "rxjs/add/operator/catch"; import "rxjs/add/observable/throw"; import "rxjs/add/operator/map"; import "rxjs/add/observable/of"; import { Employee } from "./employee"; @Injectable() export class FormPosterService { private baseUrl = "api/employee"; constructor(private http: Http) {} private extractData(res: Response) { const body = res.json(); return body.fields || {}; } private handleError(error: Response): Observable<any> { console.error("observable error: ", error); return Observable.throw(error.statusText); } postEmployeeForm(employee: Employee): Observable<Employee> { const body = JSON.stringify(employee); const headers = new Headers({ "Content-Type": "application/json" }); const options = new RequestOptions({ headers: headers }); return this.http .post(this.baseUrl, body, options) .map(this.extractData) .catch(this.handleError); } }
submitForm(form: NgForm) { console.log(this.model); console.log(form.value); // validate form this.validatePrimaryLanguage(this.model.primaryLanguage); if (this.hasPrimaryLanguageError) { return; } this.formPoster .postEmployeeForm(this.model) .subscribe( data => console.log("success: ", data), err => console.log("error: ", err) ); }
export class FormPosterService { private baseUrl = "api/employee";
namespace AngularTemplateDrivenFormsLab.Models { public class Employee { public int Id { set; get; } public string FirstName { get; set; } public string LastName { get; set; } public bool IsFullTime { get; set; } public string PaymentType { get; set; } public string PrimaryLanguage { get; set; } } }
using Microsoft.AspNetCore.Mvc; using AngularTemplateDrivenFormsLab.Models; namespace AngularTemplateDrivenFormsLab.Controllers { [Route("api/[controller]")] public class EmployeeController : Controller { public IActionResult Post([FromBody] Employee model) { //todo: save model model.Id = 100; return Created("", new { fields = model }); } } }
{"fields":{"id":100,"firstName":"Vahid","lastName":"N","isFullTime":true,"paymentType":"FullTime","primaryLanguage":"Persian"}}
private extractData(res: Response) { const body = res.json(); return body.fields || {}; }
data => console.log("success: ", data)
[HttpGet("/api/[controller]/[action]")] public IActionResult Languages() { string[] languages = { "Persian", "English", "Spanish", "Other" }; return Ok(languages); }
private extractLanguages(res: Response) { const body = res.json(); return body || {}; } getLanguages(): Observable<any> { return this.http .get(`${this.baseUrl}/languages`) .map(this.extractLanguages) .catch(this.handleError); }
languages = []; ngOnInit() { this.formPoster .getLanguages() .subscribe( data => this.languages = data, err => console.log("get error: ", err) ); }
<h3 *ngIf="languages.length == 0">Loading...</h3> <div class="container" *ngIf="languages.length > 0">
>npm install >ng build --watch
>dotnet restore >dotnet watch run
با TypeScript چه چیزهایی به دست خواهیم آورد؟
یک نکته مهم این است که این زبان به خوبی در Visual Studio پشتیبانی میشود و قابلیت Intellisense نوشتن برنامه به این زبان را دلپذیرتر خواهد کرد و از طرفی دیگر به نظر من یکی از مهمترین مزیت هایی که TypeScript در اختیار ما قرار میدهد این است که میتوانیم به صورت Syntax آشنای شی گرایی کد نویسی کنیم و خیلی راحتتر کدهای خود را سازمان دهی کرده و از نوشتن کدهای تکراری اجتناب کنیم.
یکی دیگر از مزیتهای مهم این زبان این است که این زبان از Static Typing به خوبی پشتیبانی میکند. این بدین معنی است که شما ابتدا باید متغیرها را تعریف کرده و نوع آنها را مشخص نمایید و هم چنین در هنگام پاس دادن مقادیر به پارامترهای توابع باید حتما به نوع داده ای آنها دقت داشته باشید چون کامپایلر بین انواع داده ای در TypeScript تمایز قایل است و در صورت رعایت نکردن این مورد شما با خطا مواجه خواهید شد. این تمایز قایل شدن باعث میشود که برنامه هایی خواناتر داشته باشیم از طرفی باعث میشود که خطا یابی و نوشتن تست برای برنامه راحتتر و تمیزتر باشد. بر خلاف JavaScript، در TypeScript(به دلیل پشتیبانی از شی گرایی) میتوانیم علاوه بر داشتن کلاس، اینترفیس نیز داشته باشیم و در حال حاضر مزایای استفاده از اینترفیس بر کسی پوشیده نیست.
به دلیل اینکه کدهای TypeScript ابتدا کامپایل شده و بعد تبدیل به کدهای JavaScript میشوند در نتیجه قبل از رسیدن به مرحله اجرای پروژه، ما از خطاهای موجود در کد خود مطلع خواهیم شد.
البته این نکته را نیز فراموش نخواهیم کرد که این زبان تازه متولد شده است(سال 2012 توسط Anders Hejlsberg) و همچنان در حال توسعه است و این در حال حاضر مهمترین عیب این زبان میتواند باشد چون هنوز به پختگی سایر زبانهای اسکریپتی در نیامده است.
در ذیل یک مثال کوچک به زبان TypeScript و JavaScript را برای مقایسه در خوانایی و راحتی کد نویسی قرار دادم:
TypeScript:
class Greeter { greeting: string; constructor (message: string) { this.greeting = message; } greet() { return "Hello, " + this.greeting; } }
var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.prototype.greet = function () { return "Hello, " + this.greeting; }; return Greeter; })();
Program : یک برنامه TypeScript مجموعه ای از یک یا چند Source File است. این Source Fileها شامل کدهای پیاده سازی برنامه هستند ولی در خیلی موارد برای خوانایی بیشتر برنامه میتوان فقط تعاریف را در این فایلهای سورس قرار داد.
Module: ماژول در TypeScript شبیه به مفاهیم فضای نام یا namespace در دات نت است و میتواند شامل چندین کلاس یا اینترفیس باشد.
Class : مشابه به مفاهیم کلاس در دات نت است و دقیقا همان مفهوم را دارد. یک کلاس میتواند شامل چندین تابع و متغیر با سطوح دسترسی متفاوت باشد. در TypeScript مجاز به استفاده از کلمات کلیدی public و private نیز میباشید. یک کلاس در Typescript میتواند یک کلاس دیگر را توسعه دهد(ارث بری در دات نت) و چندین اینترفیس را پیاده سازی نماید.
Interface: یک اینترفیس فقط شامل تعاریف است و پیاده سازی در آن انجام نخواهد گرفت. یک اینترفیس میتواند چندین اینترفیس دیگر را توسعه دهد.
Function: معادل متد در دات نت است. میتواند پارامتر ورودی داشته باشد و در صورت نیاز یک مقدار را برگشت دهد.
Scope: دقیقا تمام مفاهیم مربوط به محدوده فضای نام و کلاس و متد در دات نت در این جا نیز صادق است.
آماده سازی Visual Studio برای شروع به کار
در ابتدا باید Template مربوطه به TypeScript را نصب کنید تا از طریف VS.Net بتوانیم به راحتی به این زبان کد نویسی کنیم. میتوانید فایل نصب را از اینجا دانلود کنید. بعد از نصب از قسمت Templateهای موجود گزینه Html Application With TypeScript را انتخاب کنید
یا از قسمت Add در پروژههای وب خود نظیر MVC گزینه TypeScript File را انتخاب نمایید.
در پست بعدی کد نویسی با این زبان را آغاز خواهیم کرد.
$(<Macro_Name>)
$(OutDir) یا $(ProjectName)
Copy $(OutDir)*.* %WinDir%
Copy bin\Debug\*.* %WinDir%
Copy "$(ProjectDir)$(OutDir)*.*" c:\test
"$(ProjectDir)postBuild.bat" "$(SolutionPath)"
echo --------------------------------------------------------------------------- echo Copy "$(ProjectDir)$(OutDir)*.*" c:\test --Starting... Copy "$(ProjectDir)$(OutDir)*.*" c:\test if errorlevel 1 goto error echo Copy "$(ProjectDir)$(OutDir)*.*" c:\test --DONE! echo --------------------------------------------------------------------------- echo --------------------------------------------------------------------------- echo Copy $(OutDir)*.* c:\test --Starting... Copy $(OutDir)*.* c:\test if errorlevel 1 goto error echo Copy $(OutDir)*.* c:\test --DONE! echo --------------------------------------------------------------------------- goto ok :error echo POSTBUILDSTEP for $(ProjectName) FAILED notepad.exe exit 1 :ok echo POSTBUILDSTEP for $(ProjectName) COMPLETED OK
if $(ConfigurationName) == Release ( gacutil.exe /i "$(SolutionDir)$(OutDir)$(TargetFileName)" )
... <PropertyGroup> <PostBuildEvent>echo --------------------------------------------------------------------------- echo Copy "$(ProjectDir)$(OutDir)*.*" c:\test --Starting... Copy "$(ProjectDir)$(OutDir)*.*" c:\test if errorlevel 1 goto error echo Copy "$(ProjectDir)$(OutDir)*.*" c:\test --DONE! echo --------------------------------------------------------------------------- echo --------------------------------------------------------------------------- echo Copy $(OutDir)*.* c:\test --Starting... Copy $(OutDir)*.* c:\test if errorlevel 1 goto error echo Copy $(OutDir)*.* c:\test --DONE! echo --------------------------------------------------------------------------- goto ok :error echo POSTBUILDSTEP for $(ProjectName) FAILED notepad.exe exit 1 :ok echo POSTBUILDSTEP for $(ProjectName) COMPLETED OK</PostBuildEvent> </PropertyGroup> ...