ضمنا سعی کنید دچار over engineering (مدام لایه جدید اختراع کردن) و طراحی باقلوایی نشید.
چگونه کد قابل تست بنویسیم - قسمت اول
ضمنا سعی کنید دچار over engineering (مدام لایه جدید اختراع کردن) و طراحی باقلوایی نشید.
U+202A: LEFT-TO-RIGHT EMBEDDING (LRE)
U+202B: RIGHT-TO-LEFT EMBEDDING (RLE)
U+202D: LEFT-TO-RIGHT OVERRIDE (LRO)
U+202E: RIGHT-TO-LEFT OVERRIDE (RLO)
U+202C: POP DIRECTIONAL FORMATTING (PDF)
using System;
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace RleTests
{
class Program
{
const char RightToLeftEmbedding = (char)0x202B;
const char PopDirectionalFormatting = (char)0x202C;
static string FixWeakCharacters(string data)
{
if (string.IsNullOrWhiteSpace(data)) return string.Empty;
var weakCharacters = new[] { @"\", "/", "+", "-", "=", ";", "$" };
foreach (var weakCharacter in weakCharacters)
{
data = data.Replace(weakCharacter, RightToLeftEmbedding + weakCharacter + PopDirectionalFormatting);
}
return data;
}
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();
FontFactory.Register("c:\\windows\\fonts\\Arial.ttf");
Font tahoma = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H);
var table1 = new PdfPTable(1);
table1.WidthPercentage = 100;
var pdfCell = new PdfPCell
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
Border = 0,
Phrase = new Phrase(FixWeakCharacters(
"تاریخ: " + "1390/11/18" + Environment.NewLine +
"شماره پروژه: " + "1/2/3/4/56" + Environment.NewLine +
"اسلش: " + " 12/A/13 " + Environment.NewLine +
"بک اسلش: " + " 12\\13\\14 " + Environment.NewLine +
"مساوی و جمع: " + " 2+3=5 " + Environment.NewLine +
"سمی کولون: " + " 2=1+1; " + Environment.NewLine +
"دلار: " + "12$" + Environment.NewLine +
"کاما: " + "12,34,67" + Environment.NewLine +
"نقطه: " + "12.34" + Environment.NewLine +
"پرانتز: " + "متن (ساده)"
),
tahoma)
};
table1.AddCell(pdfCell);
pdfDoc.Add(table1);
}
Process.Start("Test.pdf");
}
}
}
<span dir="ltr" style="display:inline">1390/11/19</span>
U+202A: LEFT-TO-RIGHT EMBEDDING (LRE)
U+202B: RIGHT-TO-LEFT EMBEDDING (RLE)
U+202D: LEFT-TO-RIGHT OVERRIDE (LRO)
U+202E: RIGHT-TO-LEFT OVERRIDE (RLO)
U+202C: POP DIRECTIONAL FORMATTING (PDF)
using System;
using System.Diagnostics;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace RleTests
{
class Program
{
const char RightToLeftEmbedding = (char)0x202B;
const char PopDirectionalFormatting = (char)0x202C;
static string FixWeakCharacters(string data)
{
if (string.IsNullOrWhiteSpace(data)) return string.Empty;
var weakCharacters = new[] { @"\", "/", "+", "-", "=", ";", "$" };
foreach (var weakCharacter in weakCharacters)
{
data = data.Replace(weakCharacter, RightToLeftEmbedding + weakCharacter + PopDirectionalFormatting);
}
return data;
}
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();
FontFactory.Register("c:\\windows\\fonts\\Arial.ttf");
Font tahoma = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H);
var table1 = new PdfPTable(1);
table1.WidthPercentage = 100;
var pdfCell = new PdfPCell
{
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
Border = 0,
Phrase = new Phrase(FixWeakCharacters(
"تاریخ: " + "1390/11/18" + Environment.NewLine +
"شماره پروژه: " + "1/2/3/4/56" + Environment.NewLine +
"اسلش: " + " 12/A/13 " + Environment.NewLine +
"بک اسلش: " + " 12\\13\\14 " + Environment.NewLine +
"مساوی و جمع: " + " 2+3=5 " + Environment.NewLine +
"سمی کولون: " + " 2=1+1; " + Environment.NewLine +
"دلار: " + "12$" + Environment.NewLine +
"کاما: " + "12,34,67" + Environment.NewLine +
"نقطه: " + "12.34" + Environment.NewLine +
"پرانتز: " + "متن (ساده)"
),
tahoma)
};
table1.AddCell(pdfCell);
pdfDoc.Add(table1);
}
Process.Start("Test.pdf");
}
}
}
<span dir="ltr" style="display:inline">1390/11/19</span>
File.WriteAllText(path, data, Encoding.UTF8);
using System.Threading.Tasks; namespace Async05 { class Program { static void Main(string[] args) { var res = doSomethingAsync().Result; } static async Task<int> doSomethingAsync() { await Task.Delay(1); return 1; } } }
using System; using System.Collections.Generic; using System.Net; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Async05 { class Program { static void Main(string[] args) { var task = showTitlesAsync(new[] { "http://www.google.com", "https://www.dntips.ir" }); task.Wait(); Console.WriteLine(); Console.WriteLine("Press any key to exit..."); Console.ReadKey(); } static async Task showTitlesAsync(IEnumerable<string> urls) { foreach (var url in urls) { var title = await getTitleAsync(url); Console.WriteLine(title); } } static async Task<string> getTitleAsync(string url) { var data = await new WebClient().DownloadStringTaskAsync(url); return getTitle(data); } private static string getTitle(string data) { const string patternTitle = @"(?s)<title>(.+?)</title>"; var regex = new Regex(patternTitle); var mc = regex.Match(data); return mc.Groups.Count == 2 ? mc.Groups[1].Value.Trim() : string.Empty; } } }
static async Task showTitlesAsync(IEnumerable<string> urls) { foreach (var url in urls) { try { var title = await getTitleAsync(url); Console.WriteLine(title); } catch (Exception ex) { Console.WriteLine(ex); } } }
System.Net.WebException: The remote server returned an error: (502) Bad Gateway. System.Net.WebException: The remote server returned an error: (502) Bad Gateway. Press any key to exit...
public async Task<double> GetSum2Async() { try { var task1 = GetNumberAsync(); var task2 = GetNumberAsync(); var compositeTask = Task.WhenAll(task1, task2); await compositeTask.ContinueWith(x => { }); return compositeTask.Result[0] + compositeTask.Result[1]; } catch (Exception ex) { //todo: log ex throw; } }
public async Task<double> GetSumAsync() { var leftOperand = await GetNumberAsync(); var rightOperand = await GetNumberAsync(); return leftOperand + rightOperand; }
using System; using System.Threading.Tasks; namespace Async01 { class Program { static void Main(string[] args) { Test2(); Test(); Console.ReadLine(); GC.Collect(); GC.WaitForPendingFinalizers(); Console.ReadLine(); } public static async Task Test() { throw new Exception(); } public static async void Test2() { throw new Exception(); } } }
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
using System; using System.Threading.Tasks; namespace Async01 { class Program { static void Main(string[] args) { TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException; //Test2(); Test(); Console.ReadLine(); GC.Collect(); GC.WaitForPendingFinalizers(); Console.ReadLine(); } private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) { e.SetObserved(); Console.WriteLine(e.Exception); } public static async Task Test() { throw new Exception(); } public static async void Test2() { throw new Exception(); } } }
Task.Factory.StartNew(() => { throw new Exception(); }); Thread.Sleep(100); GC.Collect(); GC.WaitForPendingFinalizers();
<configuration> <runtime> <ThrowUnobservedTaskExceptions enabled="true"/> </runtime> </configuration>
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { try { ClickMeButton.Tapped += async (sender, args) => { throw new Exception(); }; } catch (Exception ex) { // This won’t catch exceptions! TextBlock1.Text = ex.Message; } }
public delegate void TappedEventHandler(object sender, TappedRoutedEventArgs e);
var personViewModel = { firstName: ko.observable("Masoud"), lastName: ko.observable("Pakdel") this.fullName = ko.computed(function() { return this.firstName() + " " + this.lastName(); }, this); };
<span data-bind='text: fullName'></span>
function Product(name, price) { this.name = ko.observable(name); this.price = ko.observable(price); }
this.shoppingCart = ko.observableArray([ new Product("Beer", 10.99), new Product("Brats", 7.99), new Product("Buns", 1.49) ]);
<table> <thead><tr> <th>Product</th> <th>Price</th> </tr></thead> <tbody data-bind='foreach: shoppingCart'> <tr> <td data-bind='text: name'></td> <td data-bind='text: price'></td> </tr> </tbody> </table>
<button data-bind='click: addProduct'>Add Beer</button>
this.addProduct = function() { this.shoppingCart.push(new Product("More Beer", 10.99)); };
function PersonViewModel() { this.firstName = ko.observable("John"); this.lastName = ko.observable("Smith"); this.checkout = function () { alert("Trying to checkout"); }; this.fullName = ko.computed(function(){ return this.firstName() + " " + this.lastName(); }, this); this.shoppingCart = ko.observableArray([ new Product("Beer", 10.99), new Product("Brats", 7.99), new Product("Buns", 1.49) ]); this.addProduct = function () { this.shoppingCart.push(new Product("More beer", 10.99)); }; };
this.removeProduct = function(product) { self.shoppingCart.remove(product); };
function PersonViewModel() { var self = this;
<tr> <td data-bind='text: name'></td> <td data-bind='text: price'></td> <td><button data-bind='click: $root.removeProduct'>Remove</button></td> </tr>
یک نام کاربری انتخاب کرده و به مرحله بعد بروید.
نام کاربری را وارد کنید و نقش Global Administrator را به آن اختصاص دهید. مدیران کلی به یک آدرس ایمیل متناوب هم نیاز دارند. به مرحله بعد بروید.
بر روی Create کلیک کنید و کلمهی عبور موقتی را کپی کنید. پس از اولین ورود باید کلمه عبور را تغییر دهید.
یک اپلیکیشن ASP.NET بسازید
گزینه Organizational Accounts را انتخاب کنید. نام دامنه خود را وارد کنید و سپس گزینه Single Sign On, Read directory data را انتخاب کنید. به مرحله بعد بروید.
نکته: در قسمت More Options می توانید قلمرو اپلیکیشن (Application ID URI) را تنظیم کنید. تنظیمات پیش فرض برای اکثر کاربران مناسب است اما در صورت لزوم میتوانید آنها را ویرایش کنید، مثلا از طریق Windows Azure Portal دامنههای سفارشی خودتان را تنظیم کنید.
اگر گزینه Overwrite را انتخاب کنید اپلیکیشن جدیدی در Windows Azure برای شما ساخته خواهد شد. در غیر اینصورت فریم ورک سعی میکند اپلیکیشنی با شناسه یکسان پیدا کند (در پست متدهای احراز هویت در VS 2013 به تنظیمات این قسمت پرداخته شده).
اطلاعات مدیر کلی دامنه در Active Directory خود را وارد کنید (Credentials) و پروژه را با کلیک کردن بر روی Create Project بسازید.
با کلیدهای ترکیبی Ctrl + F5، اپلیکیشن را اجرا کنید. مرورگر شما باید یک اخطار SSL Certificate به شما بدهد. این بدین دلیل است که مدرک استفاده شده توسط IIS Express مورد اعتماد (trusted) نیست. این اخطار را بپذیرید و اجازه اجرا را به آن بدهید. پس از آنکه اپلیکیشن خود را روی Windows Azure منتشر کردید، این پیغام دیگر تولید نمیشود؛ چرا که Certificateهای استفاده شده trusted هستند.
با حساب کاربری سازمانی (organizational account) که ایجاد کردهاید، وارد شوید.
همانطور که مشاهده میکنید هم اکنون به سایت وارد شده اید.
اپلیکیشن را روی Windows Azure منتشر کنید. روی پروژه کلیک راست کرده و Publish را انتخاب کنید. در مرحله تنظیمات (Settings) مشاهده میکنید که احراز هویت حسابهای سازمانی (organizational accounts) فعال است. همچنین سطح دسترسی به خواندن تنظیم شده است. در قسمت Database رشته اتصال دیتابیس را تنظیم کنید.
حال به وب سایت Windows Azure خود بروید و توسط حساب کاربری ایجاد شده وارد سایت شوید. در این مرحله دیگر نباید خطای امنیتی SSL را دریافت کنید.
[Authorize] public async Task<ActionResult> UserProfile() { string tenantId = ClaimsPrincipal.Current.FindFirst(TenantSchema).Value; // Get a token for calling the Windows Azure Active Directory Graph AuthenticationContext authContext = new AuthenticationContext(String.Format(CultureInfo.InvariantCulture, LoginUrl, tenantId)); ClientCredential credential = new ClientCredential(AppPrincipalId, AppKey); AuthenticationResult assertionCredential = authContext.AcquireToken(GraphUrl, credential); string authHeader = assertionCredential.CreateAuthorizationHeader(); string requestUrl = String.Format( CultureInfo.InvariantCulture, GraphUserUrl, HttpUtility.UrlEncode(tenantId), HttpUtility.UrlEncode(User.Identity.Name)); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.TryAddWithoutValidation("Authorization", authHeader); HttpResponseMessage response = await client.SendAsync(request); string responseString = await response.Content.ReadAsStringAsync(); UserProfile profile = JsonConvert.DeserializeObject<UserProfile>(responseString); return View(profile); }
کلیک کردن لینک UserProfile اطلاعات پروفایل کاربر جاری را نمایش میدهد.
return json(new { result = "ok" });
//... success: function (data) { if (data) { alert("json data: " + data.result); } }
import ProductDetails from "./components/productDetails"; // ... class App extends Component { render() { return ( <div> <NavBar /> <div className="container"> <Switch> <Route path="/products/:id" component={ProductDetails} /> <Route path="/products" render={props => ( <Products param1="123" param2="456" {...props} /> )} /> <Route path="/posts/:year/:month" component={Posts} /> <Route path="/admin" component={Dashboard} /> <Route path="/" component={Home} /> </Switch> </div> </div> ); } }
import React, { Component } from "react"; class ProductDetails extends Component { handleSave = () => { // Navigate to /products }; render() { return ( <div> <h1>Product Details - </h1> <button className="btn btn-primary" onClick={this.handleSave}> </div> ); } } export default ProductDetails;
<h1>Product Details - {this.props.match.params.id} </h1>
{this.state.products.map(product => ( <li key={product.id}> <a href={`/products/${product.id}`}>{product.name}</a> </li> ))}
import { Link } from "react-router-dom"; // ... <Link to={`/products/${product.id}`}>{product.name}</Link>
<Route path="/posts/:year/:month" component={Posts} />
<Route path="/posts/:year?/:month?" component={Posts} />
import React from "react"; const Posts = ({ match }) => { return ( <div> <h1>Posts</h1> Year: {match.params.year} , Month: {match.params.month} </div> ); }; export default Posts;
> npm i query-string --save
import queryString from "query-string"; const Posts = ({ match, location }) => { const result = queryString.parse(location.search); console.log(result); // ...
{approved: "true", sortBy: "newest"}
const { approved, sortBy } = queryString.parse(location.search);
import React from "react"; const NotFound = () => { return <h1>Not Found</h1>; }; export default NotFound;
<Route path="/" exact component={Home} />
import { Redirect, Route, Switch } from "react-router-dom"; //... import NotFound from "./components/notFound"; //... class App extends Component { render() { return ( <div> <NavBar /> <div className="container"> <Switch> //... <Route path="/not-found" component={NotFound} /> <Route path="/" exact component={Home} /> <Redirect to="/not-found" /> </Switch> </div> </div> ); } }
<Redirect from="/messages" to="/posts" />
class ProductDetails extends Component { handleSave = () => { // Navigate to /products this.props.history.push("/products"); };
const Dashboard = ({ match }) => { return ( <div> <h1>Admin Dashboard</h1> <div className="row"> <div className="col-3"> <SideBar /> </div> <div className="col"> <Route path="/admin/users" component={Users} /> <Route path="/admin/posts" component={Posts} /> </div> </div> </div> ); };
import React from "react"; import { Link } from "react-router-dom"; const SideBar = () => { return ( <ul className="list-group"> <li className="list-group-item"> <Link to="/admin/posts">Posts</Link> </li> <li className="list-group-item"> <Link to="/admin/users">Users</Link> </li> </ul> ); }; export default SideBar;
import React from "react"; const Users = () => { return <h1>Admin Users</h1>; }; export default Users;
import React from "react"; const Posts = () => { return ( <div> <h1>Admin Posts</h1> </div> ); }; export default Posts;