۱۳۸۹/۱۲/۰۷

معرفي برنامه jQueryPad


jQueryPad برنامه‌اي است قابل حمل و كم حجم براي تمرين و همچنين آزمايش سريع اسكريپت‌هاي مبتني بر jQuery . مي‌توان در قسمت سمت چپ آن قطعه‌ كد HTML ‌ايي را نوشت و در TextBox سمت راست آن، قطعه‌ كد جاوا اسكريپتي مبتني بر jQuery . سپس با فشردن دكمه F5 بلافاصله نتيجه‌ي تركيب اين دو در پايين صفحه نمايش داده مي‌شود.



اگر نياز به استفاده از نگارش خاصي از jQuery را داشتيد مي‌توان فايل js موجود در پوشه‌ي template آن‌را تغيير داد.
كار انجام شده شبيه به برنامه‌ي LINQ-Pad است؛ البته برنامه‌ي LINQ-Pad در نگارش تجاري آن داراي intellisense هم هست.

۱۳۸۹/۱۲/۰۵

محصولات آموزشي سايت Tekpub


سايت Tekpub محصولات آموزشي خودش رو به مدت فقط 24 ساعت به صورت رايگان در دسترس علاقمندان قرار داده. شامل دوره‌هاي كامل ASP.NET MVC ، Entity framework و غيره. بشتابيد!



تفاوت‌هاي پروژه‌هاي ما و پروژه‌هاي اونا!


چندي قبل پروژه‌اي دولتي در زمينه‌ي غلط يابي متون فارسي منتشر شد؛ اما ... آنچنان بازتابي در بين سايت‌هاي ايراني پيدا نكرد. حداكثر بازتاب آن مقاله‌ي روزنامه همشهري در اين حد بود كه "مايكروسافت كه يكي برامون درست كرده بود! تو چرا بي خود زحمت كشيدي!". البته روزنامه‌ي همشهري هم مقصر نيست؛ چون به طور قطع نويسنده‌ي آن با توانايي‌هاي اين برنامه در مقايسه با غلط ياب ساده مايكروسافت اطلاعات آنچناني ندارد.
از سايت‌هاي ايراني هم نبايد انتظار داشت كه براي محصولات ايراني تبليغ كنند! اگر به سايت‌هاي ايراني فعال در زمينه‌ي IT دقت كنيد بيشتر ذوق كردن‌هاي آن‌ها ناشي از كارهاي شركت خارجي است؛ مثلا:
- گوگل امروز در صفحه‌ي اولش يك عكس جديد گذاشته! (2000 تا سايت اين رو پوشش مي‌دن!)
- رئيس جديد مايكروسافت ديروز كه مي‌خواست بره سخنراني دوبار جيغ كشيد، سه بار دور سالن دويد گفت اينجا عجب شركت باحاليه!
- استيوجابز خيلي مرد نازنيني است چون فقط يك دست شلوار لي و پوليور مشكي دارد كه 10 سالش است همين فقط تنشه (هم... از شما چه پنهون وضع خود من هم بهتر از اين نيست:) )
- فيس بوك امروز عكس‌هاي شما رو در پروفايلتون هم نمايش مي‌ده!
وب سايت‌هاي لينوكسي ايراني هم كه يك چيزي توي اين مايه‌ها هستند:
اين مايكروسافت سه تا نقطه (!) باز يك سيستم عامل جديد بيرون داد، ولي اوبونتوي ما 5 ثانيه زودتر مياد بالا؛ به همين جهت هفته بعد قراره پس از طي مراحل نصب سيستم عامل كه از امروز شروع ميشه به همراه كليه دوستاني كه در اين امر مهم دخيل هستند جشن بگيريم! زنده باد آزادي!

و ... سؤال اصلي اينجا است: چرا مدل توسعه‌‌اي كه از آن صحبت شد نمي‌فروشه؟! چرا كسي براي آن تبليغ نكرد؟ چرا آنچنان كسي ذوق زده نشد؟! چرا زود فراموش شد؟

خوب؛ حالا بد نيست نگاهي هم داشته باشيم به مدل توسعه‌ي "اونا"

يكي از اين "اونا" مثلا مي‌تونه تيم سيلورلايت مايكروسافت باشه. بيائيم ببينيم "اونا" چكار مي‌كنند تا محصولاتشون بفروشه؛ ملت از شنيدن اخبار اون‌ها ذوق زده بشن؛ هزار‌تا سايت كارشون رو به رايگان تبليغ كنند و ...
- "اونا" يا كلا هر تيم توسعه‌اي تشكيل شده از يك سري آدم! هر كدام از اين‌ها يا در سايت MSDN يا به طور جداگانه وبلاگ دارند و كاري رو كه به طور منظم انجام مي‌دن، ارسال جزئياتي اندك از پيشرفت‌هاي حاصل شده است. مثلا آقاي TimHeuer هر از چندگاهي اين كار رو مي‌كنه. به اين صورت ديگه روزنامه همشهري چاپ نيويورك نمياد بنويسه، Adobe كه يكي برامون درست كرده بود! تو چرا بي‌خود زحمت كشيدي! چون الان روزنامه‌ي نيويورك تايمز مي‌دونه جزئيات كاري كه انجام شده به مرور زمان چي بوده.
- "اونا" قسمتي رو در سايت MSDN دارند به نام Silverlight TV . يك نفر رو هم استخدام كردن به نام آقاي جان پاپا! تا بياد براشون با اعضاي مختلف تيم مصاحبه كنه و يك سري از جزئيات رو بيشتر براي عموم مردم توضيح بده.
- "اونا" هر از چندگاهي سمينار برگزار مي‌كنند: (+). ميان پز مي‌دن ما اينكار رو كرديم اونكار رو كرديم؛ دنيا، بدونيد ما چقدر عالي هستيم!
- "اونا" يك bug tracking system دارند. يك features suggestion system دارند: (+) . مردم الان مي‌دونند اگر باگي رو در سيستم پيدا كردند، كجا بايد گزارش بدن. اگر نياز به ويژگي جديدي داشتند بايد چكار كنند. صرفا با يك صفحه‌ي ثابت كه لينك دريافت دو تا فايل رو گذاشته مواجه نيستند.
- "اونا" يك فوروم مخصوص هم براي Silverlight درست كردند تا استفاده كننده‌ها بيان ابتدايي‌ترين تا پيشرفته‌ترين سوالات خودشون رو مطرح كنند. نرفتند اون پشت قايم بشن! يا بگن اين ايميل ما است؛ دوست داشتيد ايميل بزنيد ما هم وقت كرديم جواب مي‌ديم!
- "اونا" مستندات و راهنماي بسيار كامل، قوي و قابل مرور تحت وب دارند: (+).
- "اونا" اگر كارشون را رايگان و سورس باز مي‌خواهند ارائه دهند از يك سورس كنترل استفاده مي‌كنند: (+).به رها كردن يك تكه سورس كد در ملاء عام كار سورس باز نمي‌گن! هر كاري آداب و اصول خودش رو داره। شما كه نمياي بچه‌ت رو بذاري سر راه و بري؟! به اين اميد كه خودش patch ميشه، خودش به روز ميشه، يكي پيدا ميشه تا دستي به سرش بكشه!
البته اين مورد جديدا جهت پروژه غلط ياب ياد شده راه اندازي شده: (+) ولي فكر نمي‌كنم كسي متوجه شده باشه، چرا؟! چون اخبار رو اين روزها علاقمندان از طريق فيدهاي RSS دنبال مي‌كنند؛ نه با مراجعه‌ي هر روزه به يك سايت. انتظار بي‌موردي است كه استفاده‌ كنندگان هر روز به سايت ما سر بزنند تا ببينند چه خبره! به همين جهت RSS اختراع شده. همچنين پروژه اختصاصي فارسي و سورس كنترل انگليسي هم همخواني ندارند.
- "اونا" اكانت توئيتر دارند: (+). "اونا" اكانت فيس بوك دارند: (+). "اونا" از اين امكانات براي گزارش دادن رخدادهاي داخلي خودشون استفاده مي‌كنند. يكي از ابزارهاي مهم تبليغاتي اون‌ها است. كلا رسانه‌ها رو در دنياي غرب به عصر قبل و بعد از توئيتر تقسيم بندي مي‌كنند. پيش از توئيتر اخبار تهيه مي‌شد و تبديل به خوراك اطلاعاتي عموم مي‌شد؛ الان اطلاعات موجود در توئيتر، جمع آوري، آناليز و تحليل مي‌شود و سپس تبديل به خوراك خبرگزاري‌ها مي‌گردد.
- "اونا" براي ارائه دانلود‌هاشون ديتاسنتر اختصاصي دارند. جايي خوندم مساحت ديتاسنتر‌هاي فعلي گوگل در حد يكي از ايالت‌هاي آمريكا شده ...؛ تصورش رو بكنيد كه با يك وب سايت هاست شده در يك كشور ثالث، بخواهيد يك نرم افزار 200 مگي را به هزاران نفر عرضه كنيد. يا مشكل پنهاي باند پيدا مي‌كنيد يا كند شدن سرور يا ...
- "اونا" اگر وقت كنند هر از چندگاهي براي تبليغ و توسعه كارشون كتاب هم منتشر مي‌كنند: (+)، تعدادي از اين‌ها هم رايگان است.

و ... و ... بدون رعايت اين موارد پروژه‌هاي خوب ارائه شده در اينترنت نمي‌فروشند! حتي شما دوست عزيز!

۱۳۸۹/۱۲/۰۴

بررسي آماري ميزان بد دهني برنامه نويس‌ها در صنوف مختلف!


شخصي اومده واژه‌هاي كذايي بكار رفته در كامنت‌هاي كدهاي ارسالي به GitHub رو آناليز كرده و يك سري نمودار بر اين مبنا ارائه داده:




CPP و جاوا اسكريپت كارها در صدر هستند و در اين بين PHP كارها و همچنين پيتونيست‌ها (!) جنتلمن‌ترين‌ها!
مابقي زبان‌هايي هم كه اينجا ليست نشده‌اند احتمالا هنوز اسم Version control به گوششان نخورده است!

آمار بازديدهاي سايت

از روز 21 بهمن تعداد بازديدكننده‌هاي اين وبلاگ از ايران به صفر رسيده اما از آمريكا (!) بيشتر از همه‌ جاي ديگر شده



البته احتمالا علت رو هم مي‌تونيد حدس بزنيد ...



۱۳۸۹/۱۲/۰۳

توليد فايل‌هاي اكسل حرفه‌اي بدون نياز به نصب مجموعه‌ي آفيس


عموما بر روي سرورهاي برنامه‌هاي وب، نرم افزار خاصي نصب نمي‌شود. براي مثال اگر نياز به توليد فايل اكسل بر روي سرور باشد، سرور دار بعيد است كه آفيس را براي شما نصب كند و همچنين مايكروسافت هم اين يك مورد را اصلا توصيه و پشتيباني نمي‌كند (ايجاد چندين وهله از برنامه آفيس (تعامل با اشياء COM) بر روي سرور توسط يك برنامه‌ي وب چند كاربره).
اگر سايت‌ها را هم جستجو كنيد پر است از مقالاتي مانند تبديل GridView به اكسل ... كه تنها هنر آن‌ها انتخاب قسمت table مانند GridView و رندر كردن آن در مرورگر با پسوندي به نام xls يا xlsx است. به عبارتي فايل نهايي توليد شده استاندارد نيست. فقط يك html table است با پسوند xls/xlsx كه برنامه‌ي اكسل مي‌داند به چه صورتي بايد آن‌را باز كند (كه گاها در اين بين فارسي سازي آن مشكل ساز مي‌شود). اين فايل نهايي توليدي عاري است از امكانات پيشرفته‌ و حرفه‌اي اكسل. براي مثال اضافه كردن فرمول به آن، تبديل اطلاعات به نمودارهاي اكسل به صورت خودكار، داشتن فايلي با چندين work sheet‌ مختلف، اعمال قالب‌هاي مختلف، صفحه بندي بهتر و غيره.
مايكروسافت از سال 2007 توليد فايل‌هاي آفيس را با معرفي استاندارد OpenXML كه توسط مؤسسه ايزو هم پذيرفته شده، بسيار ساده‌تر كرده است. OpenXML SDK‌ در دسترس است و توسط آن مي‌توان فايل‌هاي اكسل حرفه‌اي را بدون نياز به نصب مجموعه‌ي آفيس توليد كرد. كار كردن با OpenXML SDK هم در نگاه اول شايد ساده به نظر برسد اما آن هم ريزه كاري‌هاي خاص خودش را دارد كه نمونه‌اي از آن‌را در مطلب "توليد فايل Word بدون نصب MS Word بر روي سرور" مي‌توانيد مشاهده كنيد. به عبارتي اين مجموعه جهت نوشتن كتابخانه‌هاي ويژه‌ي شما باز است ...
در اين بين يكي از حرفه‌اي‌ترين كتابخانه‌هايي كه امكانات توليد فايل‌هاي اكسل را به كمك OpenXML SDK‌ سهولت مي‌بخشد، كتابخانه‌ي سورس باز EPPlus است:


مثالي در مورد نحوه‌ي استفاده از آن:
مي‌خواهيم يك DataTable را به يك فايل اكسل واقعي (نه يك html table با پسوند xlsx) تبديل كنيم با اين شرايط كه يكي از قالب‌هاي جديد آفيس به آن اعمال شود؛ جمع كل يكي از ستون‌ها توسط اكسل محاسبه گرديده و همچنين عرض دقيق ستون‌ها نيز در برنامه تنظيم گردد. نموداري نيز به صورت خودكار اين اطلاعات را نمايش دهد:




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;
}
}
}

۱۳۸۹/۱۱/۲۹

نمونه سوالات مصاحبه استخدامي


مطلبي رو در سايت آقاي اسكات هنسلمن ديدم كه به نظرم براي برگرداندن به فارسي جالب اومد. شايد باعث شود كه اندكي به فكر فرو رويم كه ... چكار داريم مي‌كنيم و قرار است به كجا برويم/برسيم.

نمونه سوالات مصاحبه استخدامي برنامه نويس‌هاي ارشد

  • - آيا هنوز كد مي‌نويسيد؟ آيا به آن علاقمنديد؟!
  • - آيا مي‌دانيد SOLID چيست؟
  • - آيا مي‌دانيد SRP مخفف چيست و چه اهميتي دارد؟
  • - پروژه‌اي مبتني بر يك فناوري جديد به شما انتساب داده شده است. چگونه آن‌را آغاز خواهيد كرد؟
  • - در مورد IOC يا Inversion of control چه مي‌دانيد؟ ارتباط آن با dependency injection چيست؟
  • - برنامه 2 tier با برنامه‌ي 3 tier چه تفاوتي دارد؟
  • - فلسفه‌ي وجودي Interface چيست و چه اهميتي دارد؟
  • - الگوي Repository را شرح دهيد. الگوي Factory‌ چيست؟ چرا الگوهاي طراحي برنامه نويسي شيءگرا مهم هستند؟
  • - Anti-patterns كدامند؟ توضيح دهيد.
  • - آيا تابحال اسم Gang of Four به گوشتان خورده است؟ در چه موردي است؟
  • - ارتباط الگوهاي MVP ، MVC و MVVM در چيست؟ هر كدام از اين الگوها در چه زماني‌هايي بهتر است بكار گرفته شوند؟
  • - مفهوم جداسازي وابستگي‌ها (Separation of Concerns) چيست. مزايا و معايب آن كدامند؟
  • - سه ويژگي اصلي طراحي شيءگرا را نام برده و توضيح دهيد.
  • - يك الگوي طراحي را توضيح دهيد كه در خانواده‌ي الگوي Factory قرار نمي‌گيرد. اين الگو چه زماني بهتر است بكار برده شود و چگونه؟
  • - فرض كنيد يك پروژه‌ي قديمي را كه از مشكلات حاد نگهداري رنج مي‌برد، به شما انتساب داده‌اند. چه فاكتورها و اقداماتي را جهت بهبود اين وضعيت درنظر گرفته و چگونه برنامه را به سمت يك پروژه‌ي پايدار پيش خواهيد برد؟
  • - مفهوم Service Orientation چه اثري را بر طراحي سيستم‌ها خواهد گذاشت؟ كجاها بهتر است استفاده شود؟
  • - در مورد portfolio تمام برنامه‌هايي كه تاكنون بر روي آن‌ها كار كرده‌ايد توضيح دهيد. شما چه نقشي در طراحي آن داشته‌‌ايد؟
  • - منهاي بانك‌هاي اطلاعاتي رابطه‌اي، با چه روش‌هايي جهت ذخيره سازي اطلاعات آشنايي داريد؟ مزايا و معايب آن‌ها چيست؟
  • - در مورد مفهوم convention over configuration توضيح دهيد. آخرين مثال عملي كه در اين مورد ديده‌ايد چه بوده است؟
  • - در مورد سيستم‌هاي بدون حالت و با حالت (stateless and stateful) توضيح دهيد. اثر هر كدام بر parallelism چيست؟
  • - تفاوت‌هاي بين Stubs و Mocks چيست و از هر كدام در كجاها استفاده خواهيد كرد؟
  • - مفهوم YAGNI را به همراه يك مثال عملي توضيح دهيد.
  • - sandbox چه معنايي دارد؟ آيا مي‌توانيد مثال‌هايي عملي از اين مفهوم را در سيستم‌هاي موجود نام ببريد؟
- در مورد Concurrency به سوالات زير پاسخ دهيد:
  • - حالت‌هاي با و بدون قفل در مدل‌هاي Concurrency چه تفاوتي دارند؟
  • - زمانيكه از مدل‌هاي با قفل و يا بدون قفل استفاده مي‌كنيد ممكن است به چه مشكلاتي برخورد كنيد؟
  • - مفهوم resource contention را توضيح دهيد.
  • - مدل بر مبتني بر وظيفه با مدل مبتني بر ريسمان چه تفاوت‌هايي دارند؟ ( task-based model & threaded model )
  • - تفاوت‌هاي بين asynchrony و concurrency را توضيح دهيد.

۱۳۸۹/۱۱/۲۶

‫دریافت کل یک مخزن SVN به کمک برنامه نویسی


تمام قابليت‌هاي موجود در SVN به كمك برنامه نويسي هم قابل دسترسي هستند. براي مثال تهيه خروجي از يك مخزن SVN به همراه تمامي فايل‌ها و ساختار آن. SVN به زبان C نوشته شده است و API آن نيز مبتني بر همين زبان است اما يك سري محصور كننده براي استفاده از آن در ساير زبان‌هاي برنامه نويسي هم موجود است. براي مثال معروفترين آن‌ها جهت استفاده به كمك دات نت فريم ورك كتابخانه‌ي SharpSVN است. پس از دريافت و افزودن ارجاعي به اسمبلي آن، چند سطر ذيل كار دريافت يك مخزن SVN را به صورت تمام و كمال انجام خواهد داد:

using SharpSvn;
...
using (var sc = new SvnClient())
{
var target = SvnTarget.FromUri(new Uri("http://someproject.googlecode.com/svn/trunk/"));
var finalSaveToDir = "somepath ..."; //Note: this path should not exist
sc.Export(target, finalSaveToDir);
}

نمونه‌اي از كاربردها:
- راه اندازي يك سايت براي دريافت ساده‌تر مخازن كد براي مثال Google-code يا source forge و امثال آن.

۱۳۸۹/۱۱/۲۵

‫نکات نصب برنامه‌های ASP.NET 4.0 بر روی IIS 6


سه نكته مهم حين توزيع برنامه‌هاي ASP.NET 4.0 بر روي IIS 6.0 نسبت به ساير نگارش‌هاي قبلي وجود دارند كه بايد در نظر گرفته شوند:

الف) پس از اتقاي برنامه از نگارش‌هاي قبلي به دات نت 4 (با فرض اينكه دات نت 4 بر روي سرور نصب است)، پيغام 404 يا به عبارتي فايل مورد نظر بر روي سرور يافت نشد را دريافت مي‌كنيد (با تمام فايل‌هاي موجود):
در كنسول IIS ، ذيل قسمت Web Services Extensions ، بايد دو مورد از حالت prohibited خارج شوند:
  • All unknown ISAPI extensions
  • ASP.NET 4.0

ب) پس از اجراي برنامه پيغام غير معتبر بودن تگ‌هاي جديد فايل Web.Config را ملاحظه مي‌كنيد:
- در برگه‌ي خواص سايت در IIS 6.0 ، اكنون امكان انتخاب ASP.NET 4.0 هم ميسر است كه حتما بايد اين مورد انتخاب گردد (تا دات نت سه و نيم اين نام تنها ASP.NET 2.0 بود). در غير اينصورت تگ‌هاي جديد فايل Web.Config شناخته نخواهند شد.

ج) بلافاصله پس از اجراي برنامه، پيغام Server Application Unavailable قابل مشاهده است:
نكته‌ي مهم ديگري كه به همراه برنامه‌هاي دات نت 4 بايد به آن توجه داشت، ضرورت اجراي آن‌ها در يك پروسه جديد است. پروسه جديد در IIS 6.0 به معناي يك Application pool جديد است. به عبارتي اگر هم اكنون بر روي IIS 6.0 شما براي مثال 2 برنامه‌ي دات نت سه و دات نت 4 قصد استفاده از يك Application pool را داشته باشند، پيغام Server Application Unavailable ظاهر خواهد شد، زيرا نمي‌توان اين دو نگارش را تحت يك پروسه اجرا كرد. براي حل اين مشكل بايد يك Application pool جديد و اختصاصي را جهت برنامه‌ي ASP.Net 4.0 خود تعريف و انتساب دهيد.

۱۳۸۹/۱۱/۲۴

وضعيت كل بلاگر و ورد پرس


در پاسخ به تعدادي از دوستان كه سوال پرسيده بودند ....
وضعيت كل بلاگر و كل وردپرس در تهران با اينترنت داتك حداقل به صورت زير است و مختص به يك سايت خاص نيست:



۱۳۸۹/۱۱/۲۳

استفاده از افزونه‌ي jQuery Autocomplete در ASP.NET


با استفاده از AutoComplete TextBoxes مي‌توان گوشه‌اي از زندگي روزمره‌ي كاربران يك برنامه را ساده‌تر كرد. مشكل مهم dropDownList ها دريك برنامه‌ي وب، عدم امكان تايپ قسمتي از متن مورد نظر و سپس نمايان شدن آيتم‌هاي متناظر با آن در اسرع وقت مي‌باشد. همچنين با تعداد بالاي آيتم‌ها هم حجم صفحه و زمان بارگذاري را افزايش مي‌دهند. راه حل‌هاي بسيار زيادي براي حل اين مشكل وجود دارند و يكي از آن‌ها ايجاد AutoComplete TextBoxes است. پلاگين‌هاي متعددي هم جهت پياده سازي اين قابليت نوشته‌ شده‌اند منجمله jQuery Autocomplete . اين پلاگين ديگر توسط نويسنده‌ي اصلي آن نگهداري نمي‌شود اما توسط برنامه نويسي ديگر در github ادامه يافته است. در ادامه نحوه‌ي استفاده از اين افزونه‌ را در ASP.NET Webforms بررسي خواهيم كرد.

الف) دريافت افزونه

لطفا به آدرس GitHub ذكر شده مراجعه نمائيد.

سپس براي مثال پوشه‌ي js را به پروژه افزوده و فايل‌هاي jquery-1.5.min.js ، jquery.autocomplete.js ، jquery.autocomplete.css و indicator.gif را در آن كپي كنيد. فايل indicator.gif به همراه مجموعه‌ي دريافتي ارائه نمي‌شود و يك آيكن loading معروف مي‌تواند باشد.
علاوه بر آن يك فايل جديد custom.js را نيز جهت تعاريف سفارشي خودمان اضافه خواهيم كرد.


ب) افزودن تعاريف افزونه به صفحه

در ذيل نحوه‌ي افزودن فايل‌هاي فوق به يك master page نمايش داده شده است.
در اينجا از قابليت‌هاي جديد ScriptManager (موجود در سرويس پك يك دات نت سه و نيم و يا دات نت چهار) جهت يكي كردن اسكريپت‌ها كمك گرفته شده است. به اين صورت تعداد رفت و برگشت‌ها به سرور به‌جاي سه مورد (تعداد فايل‌هاي اسكريپت مورد استفاده)، يك مورد (نهايي يكي شده) خواهد بود و همچنين حاصل نهايي به صورت خودكار به شكلي فشرده شده به مرورگر تحويل داده شده، سرآيندهاي كش شدن اطلاعات به آن اضافه مي‌گردد (كه در ساير حالات متداول اينگونه نيست)؛ به علاوه Url نهايي آن هم بر اساس hash فايل‌ها توليد مي‌شود. يعني اگر محتواي يكي از اين فايل‌ها تغيير كرد، چون Url نهايي تغيير مي‌كند، ديگر لازم نيست نگران كش شدن و به روز نشدن اسكريپت‌ها در سمت كاربر باشيم.

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="AspNetjQueryAutocompleteTest.Site" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:PlaceHolder Runat="server">
<link href="<%= ResolveClientUrl("~/js/jquery.autocomplete.css")%>" rel="stylesheet" type="text/css" />
</asp:PlaceHolder>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<CompositeScript>
<Scripts>
<asp:ScriptReference Path="~/js/jquery-1.5.min.js" />
<asp:ScriptReference Path="~/js/jquery.autocomplete.js" />
<asp:ScriptReference Path="~/js/custom.js" />
</Scripts>
</CompositeScript>
</asp:ScriptManager>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
علت استفاده از ResolveClientUrl در حين تعريف فايل css در اينجا به عدم مجاز بودن استفاده از ~ جهت مسير دهي فايل‌هاي css در header صفحه بر مي‌گردد.


ج) افزودن يك صفحه‌ي ساده به برنامه
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="default.aspx.cs" Inherits="AspNetjQueryAutocompleteTest._default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<asp:TextBox ID="txtShenas" runat="server" />
</asp:Content>

فرض كنيد مي‌خواهيم افزونه‌ي ذكر شده را به TextBox استاندارد فوق اعمال كنيم. ID اين TextBox در نهايت به شكل ContentPlaceHolder1_txtShenas رندر خواهد شد. البته در ASP.NET 4.0 با تنظيم ClientIDMode=Static مي‌توان ID انتخابي خود را به جاي اين ID خودكار درنظر گرفت و اعمال كرد. اهميت اين مساله در قسمت (ه) مشخص مي‌گردد.


د) فراهم آوردن اطلاعات مورد استفاده توسط افزونه‌ي AutoComplete به صورت پويا

مهم‌ترين قسمت استفاده از اين افزونه، تهيه‌ي اطلاعاتي است كه بايد نمايش دهد. اين اطلاعات بايد به صورت فايلي كه هر سطر آن حاوي يكي از آيتم‌هاي مورد نظر است، تهيه گردد. براي اين منظور مي‌توان از فايل‌هاي ASHX يا همان Generic handlers استفاده كرد:

using System;
using System.Data.SqlClient;
using System.Text;
using System.Web;

namespace AspNetjQueryAutocompleteTest
{
public class AutoComplete : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string prefixText = context.Request.QueryString["q"];
var sb = new StringBuilder();

using (var conn = new SqlConnection())
{
//todo: اين مورد بايد از فايل كانفيگ خوانده شود
conn.ConnectionString = "Data Source=(local);Initial Catalog=MyDB;Integrated Security = true";
using (var cmd = new SqlCommand())
{
cmd.CommandText = @" select Field1 ,Field2 from tblData where Field1 like @SearchText + '%' ";
cmd.Parameters.AddWithValue("@SearchText", prefixText);
cmd.Connection = conn;
conn.Open();
using (var sdr = cmd.ExecuteReader())
{
if (sdr != null)
while (sdr.Read())
{
string field1 = sdr.GetValue(0) == DBNull.Value ? string.Empty : sdr.GetValue(0).ToString().Trim();
string field2 = sdr.GetValue(1) == DBNull.Value ? string.Empty : sdr.GetValue(1).ToString().Trim();
sb.AppendLine(field1 + "|" + field2);
}
}
}
}

context.Response.Write(sb.ToString());
}

public bool IsReusable
{
get
{
return false;
}
}
}
}

در اين مثال از ADO.NET كلاسيك استفاده شده است تا به عمد نحوه‌ي تعريف پارامترها يكبار ديگر مرور گردند. اگر از LINQ to SQL يا Entity framework يا NHibernate و موارد مشابه استفاده مي‌كنيد، جاي نگراني نيست؛ زيرا كوئري‌هاي SQL توليدي توسط اين ORMs به صورت پيش فرض از نوع پارامتري هستند (+).
در اين مثال اطلاعات دو فيلد يك و دوي فرضي از جدولي با توجه به استفاده از like تعريف شده دريافت مي‌گردد. به عبارتي همان متد StartsWith معروف LINQ بكارگرفته شده است.
به صورت خلاصه افزونه، كوئري استرينگ q را به اين فايل ashx ارسال مي‌كند. سپس كليه آيتم‌هاي شروع شده با مقدار دريافتي، از بانك اطلاعاتي دريافت شده و هر كدام قرارگرفته در يك سطر جديد بازگشت داده مي‌شوند.
اگر دقت كرده باشيد در قسمت sb.AppendLine ، با استفاده از "|" دو مقدار دريافتي از هم جدا شده‌اند. عموما يك مقدار كفايت مي‌كند (در 98 درصد موارد) ولي اگر نياز بود تا توضيحاتي نيز نمايش داده شود از اين روش نيز مي‌توان استفاده كرد. براي مثال يك مقدار خاص به همراه توضيحات آن به عنوان يك آيتم نمايش داده شده مد نظر است.


ه) اعمال نهايي افزونه به TextBox

در ادامه پياده سازي فايل custom.js براي استفاده از امكانات فراهم شده در قسمت‌هاي قبل ارائه گرديده است:

function formatItem(row) {
return row[0] + "<br/><span style='text-align:justify;' dir='rtl'>" + row[1] + "</span>";
}

$(document).ready(function () {
$("#ContentPlaceHolder1_txtShenas").autocomplete('AutoComplete.ashx', {
//Minimum number of characters a user has to type before the autocompleter activates
minChars: 0,
delay: 5,
//Only suggested values are valid
mustMatch: true,
//The number of items in the select box
max: 20,
//Fill the input while still selecting a value
autoFill: false,
//The comparison doesn't looks inside
matchContains: false,
formatItem: formatItem
});
});

پس از اين مقدمات، اعمال افزونه‌ي autocomplete به textBox ايي با id مساوي ContentPlaceHolder1_txtShenas ساده است. اطلاعات از فايل AutoComplete.ashx دريافت مي‌گردد و تعدادي از خواص پيش فرض اين افزونه در اينجا مقدار دهي شده‌اند. ليست كامل آن‌ها را در فايل jquery.autocomplete.js مي‌توان مشاهده كرد.
تنها نكته‌ي مهم آن استفاده از پارامتر اختياري formatItem است. اگر در حين تهيه‌ي AutoComplete.ashx خود تنها يك آيتم را در هر سطر نمايش مي‌دهيد و از "|" استفاده نكرده‌ايد، نيازي به ذكر آن نيست. در اين مثال ويژه، فيلد يك در يك سطر و فيلد دو در سطر دوم يك آيتم نمايش داده مي‌شوند:



۱۳۸۹/۱۱/۲۱

نحوه‌ي نگاشت فيلدهاي فرمول در Fluent NHibernate


اگر با SQL Server كار كرده باشيد حتما با مفهوم و امكان Computed columns (فيلدهاي محاسبه شده) آن آشنايي داريد. چقدر خوب مي‌شد اگر اين امكان براي ساير بانك‌هاي اطلاعاتي كه از تعريف فيلدهاي محاسبه شده پشتيباني نمي‌كنند، نيز مهيا مي‌شد. زيرا يكي از اهداف مهم استفاده‌ي صحيح از ORMs ، مستقل شدن برنامه از نوع بانك اطلاعاتي است. براي مثال امروز مي‌خواهيم با MySQL‌ كار كنيم، ماه بعد شايد بخواهيم يك نسخه‌ي سبك‌تر مخصوص كار با SQLite را ارائه دهيم. آيا بايد قسمت دسترسي به داده برنامه را از نو بازنويسي كرد؟ اينكار در NHibernate فقط با تغيير نحوه‌ي اتصال به بانك اطلاعاتي ميسر است و نه بازنويسي كل برنامه (و صد البته شرط مهم و اصلي آن هم اين است كه از امكانات ذاتي خود NHibernate استفاده كرده باشيد. براي مثال وسوسه‌ي استفاده از رويه‌هاي ذخيره شده را فراموش كرده و به عبارتي ORM مورد استفاده را به امكانات ويژه‌ي يك بانك اطلاعاتي گره نزده باشيد).
خوشبختانه در NHibernate امكان تعريف فيلدهاي محاسباتي با كمك تعريف نگاشت خواص به صورت فرمول مهيا است. براي توضيحات بيشتر لطفا به مثال ذيل دقت بفرمائيد:
در ابتدا كلاس كاربر تعريف مي‌شود:

using System;
using NHibernate.Validator.Constraints;

namespace FormulaTests.Domain
{
public class User
{
public virtual int Id { get; set; }

[NotNull]
public virtual DateTime JoinDate { set; get; }

[NotNullNotEmpty]
[Length(450)]
public virtual string FirstName { get; set; }

[NotNullNotEmpty]
[Length(450)]
public virtual string LastName { get; set; }

[Length(900)]
public virtual string FullName { get; private set; } //از طريق تعريف فرمول مقدار دهي مي‌گردد

public virtual int DayOfWeek { get; private set; }//از طريق تعريف فرمول مقدار دهي مي‌گردد
}
}
در اين كلاس دو خاصيت FullName و DayOfWeek به صورت فقط خواندني به كمك private set ذكر شده، تعريف گرديده‌اند. قصد داريم روي اين دو خاصيت فرمول تعريف كنيم:

using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;

namespace FormulaTests.Domain
{
public class UserCustomMappings : IAutoMappingOverride<User>
{
public void Override(AutoMapping<User> mapping)
{
mapping.Id(u => u.Id).GeneratedBy.Identity(); //ضروري است
mapping.Map(x => x.DayOfWeek).Formula("DATEPART(dw, JoinDate) - 1");
mapping.Map(x => x.FullName).Formula("FirstName + ' ' + LastName");
}
}
}
نحوه‌ي انتساب فرمول‌هاي مبتني بر SQL را در نگاشت فوق ملاحظه مي‌نمائيد. براي مثال FullName از جمع دو فيلد نام و نام خانوادگي حاصل خواهد شد و DayOfWeek از طريق فرمول SQL ديگري كه ملاحظه مي‌نمائيد (يا هر فرمول SQL دلخواه ديگري كه صلاح مي‌دانيد).
اكنون اگر Fluent NHibernate را وادار به توليد اسكريپت متناظر با اين دو كلاس كنيم حاصل به صورت زير خواهد بود:
    create table Users (
UserId INT IDENTITY NOT NULL,
JoinDate DATETIME not null,
FirstName NVARCHAR(450) not null,
LastName NVARCHAR(450) not null,
primary key (UserId)
)
همانطور كه ملاحظه مي‌كنيد در اينجا خبري از دو فيلد محاسباتي تعريف شده نيست. اين فيلدها در تعاريف نگاشت‌ها به صورت خودكار ظاهر مي‌شوند:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true"
name="FormulaTests.Domain.User, FormulaTests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Users">
<id name="Id" type="System.Int32" unsaved-value="0">
<column name="UserId" />
<generator class="identity" />
</id>
<property name="DayOfWeek" formula="DATEPART(dw, JoinDate) - 1" type="System.Int32" />
<property name="FullName" formula="FirstName + ' ' + LastName" type="System.String" />
<property name="JoinDate" type="System.DateTime">
<column name="JoinDate" />
</property>
<property name="FirstName" type="System.String">
<column name="FirstName" />
</property>
<property name="LastName" type="System.String">
<column name="LastName" />
</property>
</class>
</hibernate-mapping>
اكنون اگر كوئري زير را در برنامه اجرا نمائيم:
var list = session.Query<User>.ToList();
foreach (var item in list)
{
Console.WriteLine("{0}:{1}", item.FullName, item.DayOfWeek);
}
به صورت خودكار به SQL ذيل ترجمه خواهد شد و اكنون نحوه‌ي بكارگيري فيلدهاي فرمول، بهتر مشخص مي‌گردد:
select
user0_.UserId as UserId0_,
user0_.JoinDate as JoinDate0_,
user0_.FirstName as FirstName0_,
user0_.LastName as LastName0_,
DATEPART(user0_.dw, user0_.JoinDate) - 1 as formula0_, --- همان فرمول تعريف شده است
user0_.FirstName + ' ' + user0_.LastName as formula1_ ---از طريق فرمول تعريف شده حاصل گرديده است
from
Users user0_

۱۳۸۹/۱۱/۱۷

اعمال تغييرات سفارشي به ويژگي AutoMapping در Fluent NHibernate


با كمك Fluent NHibernate مي‌توان نگاشت‌ها را به دو صورت خودكار و يا دستي تعريف كرد. در حالت خودكار، روابط بين كلاس‌ها بررسي شده و بدون نياز به تعريف هيچگونه ويژگي (attribute) خاصي بر روي فيلدها، امكان تشخيص خودكار حالت‌هاي كليد خارجي، روابط يك به چند، چند به چند و امثال آن وجود دارد. يا اگر نياز باشد تا اسكريپت توليدي جهت به روز رساني بانك اطلاعاتي، طول خاصي را به فيلدي اعمال كند مي‌توان از ويژگي‌هاي NHibernate validator استفاده كرد؛ مانند تعريف طول و نال نبودن يك فيلد كه علاوه بر بكارگيري اطلاعات آن در حين تعيين اعتبار ورودي دريافتي، بر روي نحوه‌ي به روز رساني بانك اطلاعاتي هم تاثير گذار است:
public class Product
{
public virtual int Id { set; get; }

[Length(120)]
[NotNullNotEmpty]
public virtual string Name { get; set; }

public virtual decimal UnitPrice { get; set; }
}
اين نگاشت خودكار يا AutoMapping ،‌ تقريبا در 90 درصد موارد كافي است. فيلد Id را بر اساس يك سري پيش فرض‌هايي كه اين مورد هم قابل تنظيم است به صورت primary key تعريف مي‌كند، طول فيلدها و نحوه‌ي پذيرفتن نال آن‌ها، از ويژگي‌هاي NHibernate validator گرفته مي‌شود و روابط بين كلاس‌ها به صورت خودكار به روابط يك به چند و مانند آن ترجمه مي‌شود و نيازي نيست تا كلاسي جداگانه را جهت مشخص سازي صريح اين موارد تهيه كرد، يا ويژگي مشخص كننده‌ي ديگري را به فيلدها افزود. اما اگر براي مثال بخواهيم در اين كلاس فيلد Name را به صورت Unique معرفي كنيم چه بايد كرد؟ به عبارتي تمام آنچه‌ كه ويژگي AutoMapping در Fluent NHibernate انجام مي‌دهد، بسيار هم عالي؛ اما فقط مي‌خواهيم مقادير يك فيلد منحصربفرد باشد. براي اين منظور اينترفيس IAutoMappingOverride تدارك ديده شده است:
public class ProductCustomMappings : IAutoMappingOverride<Product>
{
public void Override(AutoMapping<Product> mapping)
{
mapping.Id(u => u.Id).GeneratedBy.Identity(); //ضروري است
mapping.Map(p => p.Name).Unique();
}
}
در حالت استفاده از اينترفيس IAutoMappingOverride مشخص سازي نحوه‌ي توليد primary key ضروري است و سپس براي نمونه، فيلد Name به صورت منحصربفرد تعريف مي‌گردد. در اينجا كل عمليات هنوز از روش AutoMapping پيروي مي‌كند اما فيلد Name علاوه بر اعمال ويژگي‌هاي NHibernate validator، به صورت منحصربفرد نيز معرفي خواهد شد.

۱۳۸۹/۱۱/۱۵

دو خبر در مورد برنامه Reflector


شايد اين خبر رو ديده باشيد كه نگارش بعدي Reflector شركت RedGate كاملا تجاري است (به قيمت 35 دلار) و ديگر نگارش lite و رايگاني نخواهد داشت؛ برخلاف وعده‌اي كه در ابتداي كار در مورد رايگان نگه داشتن كار آقاي Lutz Roeder داده بودند. همان روز هم شركت JetBarins در تصويري به صورت ضمني اعلام كرد كه نگارش بعدي ReSharper چيزي شبيه به Reflector را به صورت سرخود ارائه خواهد داد. كامنت‌هاي آن هم جالب است. وقت كرديد بخونيد!


۱۳۸۹/۱۱/۱۴

چه زمان‌هايي يك برنامه‌ي ASP.NET ري استارت مي‌شود؟


براي ري استارت كردن يك برنامه‌ي ASP.NET حتما نيازي نيست تا IIS را متوقف و سپس راه اندازي كرد يا تنظيمات App pool برنامه را در IIS تغيير داد. روش‌هاي ديگري نيز وجود دارند كه عدم آگاهي از آن‌ها مي‌تواند سبب بروز مشكلات عديده‌اي گردد و گاها خطايابي آن‌ها بسيار مشكل است؛ زيرا ري استارت شدن برنامه = از دست رفتن آني تمام سشن‌هاي InProc تمام كاربران سايت؛ پاك شدن كش برنامه در IIS؛ از دست رفتن تمام متغيرهاي استاتيك، Application State و مواردي از اين دست:
  • - نوشتن در پوشه bin برنامه (ايجاد فايل يا ايجاد پوشه يا تغيير نام پوشه‌ها و مواردي از اين دست). (بنابراين قرار دادن بانك اطلاعاتي برنامه در اين پوشه، اشتباه بوده و به همين جهت پوشه‌ي استاندارد App_Data طراحي شده است)
  • - نوشتن در فايل web.config برنامه (به صورت دستي، حتي در حد اضافه كردن يك فاصله يا توسط خود برنامه و يا استفاده از متد File.SetLastWriteTime). در اين حالت ASP.NET FileSystemWatcher بلافاصله وارد عمل شده و برنامه را ري استارت مي‌كند. (هدف اصلي وجودي اين فايل، برخورد فقط خواندني با آن است نه ذخيره سازي تنظيمات پوياي برنامه در آن. براي ذخيره سازي تنظيمات پويا، از بانك اطلاعاتي و يا يك فايل XML مجزاي از وب كانفيگ استفاده كنيد يا مواردي مشابه)
  • - هر گونه تغييري در فايل‌ها و يا پوشه‌هاي App_WebReferences ، App_Code ، Global.asax ، machine.config ، App_GlobalResources و App_LocalResources نيز سبب ري استارت برنامه خواهند شد.
  • - با ايجاد، حذف يا تغيير نام يكي از ساب دايركتوري‌هاي واقع شده در ريشه برنامه. بنابراين اگر برنامه‌ي شما به صورت پويا پوشه‌هايي را ايجاد يا حذف مي‌كند بايد منتظر ري استارت‌هاي پي در پي باشيد (البته اين مورد با از كار انداختن FileChangesMonitor مربوط به HttpRuntime قابل حل مي‌باشد (+)، ولي همانطور كه عنوان شد به صورت پيش فرض همواره فعال است)
  • - فراخواني متد System.Web.HttpRuntime.UnloadAppDomain شبيه به همان Application.Exit در برنامه‌هاي دسكتاپ است و بلافاصله سبب خاتمه‌ي برنامه مي‌شود. قرار دادن فايل App_Offline.htm در پوشه اصلي برنامه نيز چنين رفتاري را سبب خواهد شد. علاوه بر آن تگ httpRuntime در وب كانفيگ نيز داراي گزينه‌ي enable است و تنظيم آن به false ، سبب خاتمه‌ي سرويس دهي برنامه خواهد شد.
  • - رسيدن به عدد numRecompilesBeforeAppRestart تعريف شده در فايل machine.config كه عموما به عدد 15 تنظيم شده است. اگر تغييرات زيادي را در فايل‌هاي (مرتبط با ASP.NET مانند aspx ، asmx و غيره) برنامه داده باشيد (بيشتر از 15 مورد) و نيازي به ري كامپايل اساسي وجود داشته باشد، ASP.NET FileSystemWatcher به صورت خودكار برنامه را ري استارت خواهد كرد.

۱۳۸۹/۱۱/۱۲

توليد خودكار آزمون‌هاي واحد NUnit


تعدادي ابزار براي توليد خودكار متدهاي آزمون‌هاي واحد NUnit از روي كلاس‌هاي موجود در يك اسمبلي وجود دارند كه به دو دسته تقسيم مي‌شود:

الف) آن‌هايي كه فقط نام كلاس‌هاي آزمون واحد و نام متدهاي آن‌را به صورت خودكار توليد مي‌كنند


اين ابزارها و كتابخانه‌ها، تنها كاري كه انجام مي‌دهند يافتن كلاس‌ها و متدهاي عمومي موجود در يك اسمبلي توسط Reflection و سپس توليد يك سري فايل‌ آماده از روي اين اطلاعات است. براي مثال اگر نام كلاس شما Class1 است فايلي به نام TestClass1 را توليد مي‌كنند و اگر يكي از متد‌هاي عمومي اين كلاس به نام Method1 باشد، يك متد خالي را به نام Method1Test ايجاد خواهند كرد و همين.
تبديل CodeSmith NUnit Test Generator فوق به يك T4 template كار ساده‌اي است.

ب) ابزارهايي كه علاوه بر مورد الف، سعي مي‌كنند بدنه‌اي را نيز براي متدهاي واحد توليد شده تهيه كنند


اين افزونه‌ها و برنامه‌ها سعي مي‌كنند به كمك Reflection و همچنين امكانات توليد كد موجود در VS.NET نسبت به توليد كلاس‌ها، متدها و بدنه‌هاي نمونه آن‌ها اقدام كنند. براي مثال اگر نام متد كلاسي، Method1 به همراه يك پارامتر از نوع int باشد، بدنه توليد شده به همراه وهله سازي از كلاس آن و فراخواني اين متد به همراه پارامتر آن خواهد بود.
مشكل مهم اين پروژه‌هاي سورس باز كوچك هم عدم تعهد به نگهداري آن‌ها است. براي مثال آخرين به روز رساني موجود افزونه‌ي NUnitGen شركت ناول، مخصوص VS2008 است يا آخرين به روز رساني TestGen.Net مربوط به دات نت يك است (سورسي هم كه در سايت سورس فورج قرار داده ناقص است) يا مقاله‌ي سايت CodeProject‌ كه ذكر گرديد، با نگارش‌هاي جديد NUnit درست كار نمي‌كند و كامپايل نمي‌شود.

در بين اين‌ها به نظر من Edwinyeah TestGen.Net كار جالبي را انجام داده است و چندين زبان را هم پشتيباني مي‌كند. البته همانطور كه عنوان شد توانايي بارگذاري اسمبلي‌هاي نگارش‌هاي جديد دات نت را ندارد كه موضوع مهمي نيست. سورس آن‌را مي‌توان دريافت و سپس جهت دات نت 4 كامپايل كرد. البته يك سري از كلاس‌هاي آن هم كه در سورس موجود نيستند را مي‌شود از اسمبلي كامپايل شده‌ي آن با Reflector درآورد، به پروژه اصلي اضافه و سپس كامپايل كرد!
كامپايل شده‌ي آن‌را جهت دات نت 4 از اينجا دريافت كنيد.