thuoc_tinh_cua_dot_Net

Màu nền
Font chữ
Font size
Chiều cao dòng

TRANG CHỦ ::>> E-BOOKS

Thuộc tính của .NET - 2/8/2006 13h:55

Thuộc tính là một trong những khái niệm quan trọng nhất của .NET, nó ảnh hưởng đến nhiều phương diện khác nhau của một ứng dụng .NET như khả năng giao tiếp với các thành phần COM, khả năng tạo ra trình dịch vụ, tính năng bảo mật, tính năng lưu dữ liệu của đối tượng vào tập tin...

Thuộc tính là gì?

Sức mạnh của .NET (so với các đời trước) có được phần lớn là do ý tưởng về thông tin mô tả (metadata) đem lại. Chính những thông tin này đã giúp cho các assembly tự mô tả đầy đủ chính nó, nhờ đó việc giao tiếp và sử dụng lại các chương trình viết bằng những ngôn ngữ khác nhau cũng trở nên dễ dàng, hiệu quả hơn. Việc lập trình tất nhiên cũng đơn giản hơn! Làm sao cung cấp những thông tin này? Câu trả lời là: dùng thuộc tính.

Thuộc tính là những đối tượng chuyên dùng để cung cấp thông tin mô tả cho các phần tử trong một assembly .NET. Phần tử ở đây bao gồm assembly, lớp, các thành viên của lớp (gồm hàm tạo, hàm thuộc tính, trường, hàm chức năng, tham biến, giá trị trả về), sự kiện.

Cách sử dụng thuộc tính trong C#

Có một số qui tắc bắt buộc phải tuân theo khi dùng thuộc tính để viết mã chương trình:

• Thuộc tính phải đặt trong dấu ngoặc vuông.

Ví dụ: Khi bạn tạo ra một ứng dụng loại Console trong VS.NET IDE, bạn sẽ thấy hàm Main được áp dụng thuộc tính STAThread như sau:

[STAThread]

static void Main(string[] args){

...

}

• Tên các lớp thuộc tính thường có đuôi là "Attribute" nhưng bạn có thể không ghi đuôi này.

Ví dụ: Hãy thử đổi [STAThread] thành [STAThreadAttribute] và biên dịch chương trình. Bạn sẽ thấy không có lỗi gì xảy ra.

• Thuộc tính có thể có nhiều biến thể ứng với nhiều bộ tham biến khác nhau. Khi cần truyền tham số cho thuộc tính, ghi chúng trong cặp ngoặc đơn. Riêng đối với biến thể không tham biến, có thể ghi hoặc không ghi cặp ngoặc rỗng "()". Ngoài ra, các tham số phải là các biểu thức hằng, biểu thức typeof hay biểu thức tạo mảng (như new Type[]{typeof(TargetException)}).

Ví dụ 1: Có thể thay [STAThread] bằng [STAThread()].

Ví dụ 2: Khi cần đánh dấu một lớp, hàm là "đã cũ, cần dùng phiên bản thay thế", ta có thể dùng thuộc tính ObsoleteAttribute. 1 trong 3 biến thể của thuộc tính này là:

[Obsolete(string message, bool error)]

Trong đó: message dùng để cung cấp thông tin chỉ dẫn về lớp, hàm thay thế. error dùng để hướng dẫn cho trình biên dịch biết cần làm gì khi biên dịch lớp, hàm sử dụng phần tử được áp dụng Obsolete. Nếu error bằng true, trình biên dịch báo lỗi và không biên dịch. Ngược lại, trình biên dịch chỉ cảnh báo và vẫn biên dịch bình thường.

Như vậy, ta có thể sử dụng như sau:

[Obsolete("Nên dùng lớp NewClass", false)]

public class OldClass{

...

}

// lớp này không được áp dụng thuộc tính Obsolete

public class ClientClass{

private OldClass a = new OldClass();

...

}

Khi biên dịch lớp ClientClass, VS.NET IDE sẽ thông báo ở cửa sổ Task List như hình 1:

Hình 1

Nếu bạn sửa false thành true thì bạn sẽ thấy bảng báo lỗi như hình 2:

Hình 2

Ví dụ 3: không thể dùng

private string s = "Nên dùng lớp NewClass";

[Obsolete(s, false)]

Nhưng nếu thêm const vào phần khai báo của s thì hợp lệ.

• Thuộc tính có mục tiêu áp dụng (do người viết ra thuộc tính qui định) xác định nên vị trí đặt cũng bị hạn chế. Nói chung, thuộc tính phải đặt trước mục tiêu áp dụng và không thể đứng bên trong thân hàm. Nếu thuộc tính có nhiều mục tiêu áp dụng được thì có thể chỉ định mục tiêu cụ thể bằng một trong các từ khoá: assembly, module, type, event, field, property, method, param, return.

Ví dụ:

[assembly: AssemblyTitle("Demo")] // Đúng chỗ

namespace Demo;

[assembly: AssemblyTitle("Demo")] // Sai chỗ

[type: Obsolete] // Đúng chỗ

// [method: Obsolete] // Sai chỗ

public class OldClass{

[type: Obsolete] // Sai chỗ

...

}

}

• Thuộc tính có thể đặt trong các cặp ngoặc vuông liên tiếp nhau hay đặt trong cùng một cặp ngoặc vuông nhưng cách nhau bởi dấu phẩy.

Ví dụ:

[type: Obsolete("Nên dùng lớp NewClass", false),Serializable]

tương đương với

[type: Obsolete("Nên dùng lớp NewClass", false)]

[Serializable]

• Có những thuộc tính có thể được áp dụng nhiều lần cho cùng một mục tiêu. Điều này cũng do người viết ra thuộc tính qui định.

Ví dụ 1:

// Trình biên dịch sẽ báo lỗi "Duplicate Obsolete attribute"

[type:Obsolete]

[type:Obsolete]

public class OldClass{

...

}

Ví dụ 2:

// Trình biên dịch không báo lỗi

// Thuộc tính ExpectedException ở đây là thuộc tính custom mà ta sẽ tự tạo trong phần 5-

[type: ExpectedException( typeof(xxxException) )]

[type: ExpectedException( typeof(xxxException) )]

public class OldClass{

...

}

• Một số thuộc tính có tính kế thừa. Khi bạn áp dụng những thuộc tính này cho một lớp nào đó, hãy nhớ là các lớp con của lớp đó cũng mặc nhiên được áp dụng các thuộc tính đó. Bạn sẽ thấy rõ điều này trong phần "Tạo một thuộc tính custom".

• Cuối cùng, khi sử dụng thuộc tính nào, nhớ tạo ra tham chiếu tới không gian kiểu chứa nó. Chẳng hạn như, để dùng các thuộc tính như AssemblyTitle, AssemblyVersion, cần thêm:

using System.Reflection;

Đặc điểm của thuộc tính

1. Khi thêm thuộc tính vào mã chương trình, ta đã tạo ra một đối tượng mà các thông tin của nó sẽ được lưu vào assembly chứa mục tiêu áp dụng của thuộc tính. Tùy theo thuộc tính thuộc loại custom hay p-custom (p- là pseudo) mà những thông tin này sẽ được lưu thành chỉ thị .custom hay khác (.ver, .hash, serializable,... ) trong tập mã IL.

Ví dụ: lớp OldClass sau sẽ có mã IL (xem bằng ILDasm.exe) như hình 3:

[Obsolete("Nen dung lop NewClass", false)]

[Serializable]

public class OldClass{

...

}

Hình 3

• Tuy được lưu trong assembly nhưng thuộc tính hoàn toàn không ảnh hưởng gì đến các mã lệnh khác. Thuộc tính chỉ có ý nghĩa khi có một chương trình nào đó cần đến và truy xuất nó thông qua tính năng Reflection của .NET. Dĩ nhiên, ý nghĩa của thuộc tính sẽ do chương trình đó qui định. Điều đó cũng có nghĩa là cùng một thuộc tính nhưng "dưới mắt" các chương trình đọc khác nhau sẽ có thể có công dụng khác nhau. Đây là đặc điểm đáng chú ý nhất của thuộc tính.

Ví dụ: thuộc tính Obsolete được trình biên dịch dùng để phát hiện những phần tử sẽ không được sử dụng nữa, [TestFixture] được NUnit dùng để chọn những lớp có chứa hàm kiểm tra cần được kích hoạt tự động,...

• Dữ liệu chỉ định trong thuộc tính gắn chặt với mục tiêu áp dụng của thuộc tính chứ không lỏng lẻo và do đó không linh hoạt như dữ liệu trong tập tin cấu hình. Nhờ vậy, dữ liệu mô tả lưu bằng thuộc tính an toàn hơn, khó sửa hơn.

• Thuộc tính còn có những đặc điểm khác như: có mục tiêu áp dụng xác định, có khả năng áp dụng nhiều lần cho cùng một mục tiêu, có thể được thừa kế.

Một số ví dụ minh họa ứng dụng của thuộc tính

a - Thuộc tính CLSCompliant:

Mục tiêu của .NET là tạo ra một nền tảng giao tiếp thống nhất giữa nhiều ngôn ngữ lập trình khác nhau. Để đạt được điều đó, .NET định ra 2 chuẩn là CTS và CLS, trong đó CTS bao gồm các kiểu cơ bản mà một ngôn ngữ .NET có thể chọn hỗ trợ còn CLS là một tập các qui tắc bắt buộc mọi ngôn ngữ .NET phải áp dụng cho các phần tử dùng để giao tiếp với nhau. Như vậy, một ngôn ngữ có thể hỗ trợ những kiểu mà ngôn ngữ khác không hỗ trợ. Kết quả là khi các ngôn ngữ muốn phối hợp với nhau thì những kiểu "không chung" này sẽ "phá đám", gây ra hiểu nhầm. Để tránh tình huống này, .NET tạo ra thuộc tính CLSCompliant dùng để nhờ trình biên dịch theo dõi và cảnh báo xem có phần tử nào vi phạm luật CLS hay không. Thuộc tính này có mục tiêu áp dụng là mọi phần tử.

Ví dụ:

// Kiểm tra xem mọi phần tử của assembly này có tương thích CLS không

[assembly: CLSCompliant(true)]

namespace Demo{

// Riêng: bỏ qua các phần tử của lớp này

[type: CLSCompliant(false)]

public class A{

private uint a;

public uint b;

}

public class B{

private uint a; // không bị coi là vi phạm vì có tầm vực private

public uint b; // vi phạm

}

}

b - Các thông tin mô tả về assembly:

Khi sử dụng VS.NET IDE để tạo một dự án, bạn sẽ thấy là luôn có một tập tin tên AssemblyInfo.xx (tùy theo ngôn ngữ, xx có thể là cs với C#, vb với VB.NET,...). Sau đây là nội dung tập tin AssemblyInfo.cs đã lược bỏ phần chú thích:

using System.Reflection;

using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("")]

[assembly: AssemblyDescription("")]

[assembly: AssemblyConfiguration("")]

[assembly: AssemblyCompany("")]

[assembly: AssemblyProduct("")]

[assembly: AssemblyCopyright("")]

[assembly: AssemblyTrademark("")]

[assembly: AssemblyCulture("")]

[assembly: AssemblyVersion("1.0.*")]

[assembly: AssemblyDelaySign(false)]

[assembly: AssemblyKeyFile("")]

[assembly: AssemblyKeyName("")]

(Lưu ý: Có thể bạn ngộ nhận tập tin trên là bắt buộc phải có. Nhưng không, nó chẳng qua là một công cụ mà VS.NET cung cấp, giúp bạn tập trung các thông tin chung về assembly lại một chỗ. Bạn hoàn toàn có thể xóa bỏ tập tin trên và tạo lại các mục tương tự nhưng để rải rác ở các tập tin trong dự án.)

Như bạn thấy, tập tin trên chỉ chứa toàn các thuộc tính với mục tiêu áp dụng là assembly. Những thuộc tính ấy nằm trong 2 không gian kiểu System.Reflection và System.Runtime.CompilerServices. 8 thuộc tính đầu dùng để cung cấp các thông tin chung về assembly (có thể xem những thông tin này bằng ILDasm.exe hay Windows Explorer). AssemblyVersion dùng để ghi nhận số phiên bản cho assembly, số này sẽ được CLR cần đến. Cụ thể là nếu assembly A tham chiếu đến assembly B thì trong assembly A sẽ ghi nhận phiên bản của B mà A tham chiếu. Nhờ đó, khi CLR cần tải B để hỗ trợ cho A thì CLR có thể biết được và tải đúng phiên bản thích hợp của B.

AssemblyKeyFile dùng để chỉ định tập tin chứa cặp khóa chung/riêng mà trình biên dịch sẽ dựa vào để tạo ra assembly duy nhất. Nếu không dùng AssemblyKeyFile thì có thể dùng AssemblyKeyName thay thế, chỉ khác là cần chỉ định tên của khóa đã được cài đặt vào Crypto Service Provider trên máy. Cũng có thể dùng cùng lúc cả 2 thuộc tính để chỉ định khóa; khi ấy, AssemblyKeyName sẽ được ưu tiên dùng trước.

Cuối cùng, AssemblyDelaySign dùng để yêu cầu trình biên dịch tạo ra một assembly giả duy nhất (vì chỉ cần dựa vào khóa chung) giúp cho việc thử nghiệm dễ dàng hơn. Đến khi cần triển khai ứng dụng thực sự mới phải dùng khóa riêng để tạo ra assembly duy nhất. Nhờ có AssemblyDelaySign, khóa riêng có thể được giữ bí mật bởi một người nào đó mà không làm ảnh hưởng đến quá trình phát triển phần mềm chung của cả nhóm.

Tạo một thuộc tính custom

Trong các phần trước, chúng ta đã sử dụng các thuộc tính có sẵn của .NET. Trong phần này, chúng ta sẽ tìm hiểu cách tự tạo lấy các thuộc tính cho riêng mình "xài" thông qua quá trình xây dựng thuộc tính ExpectedException.

Cũng như những thuộc tính custom có sẵn, thuộc tính tự tạo của chúng ta phải là một lớp con của lớp System.Attribute:

// Theo qui ước, tên thuộc tính nên có đuôi là Attribute

public class ExpectedExceptionAttribute : System.Attribute{

...

}

Thuộc tính tự tạo có thể có các hàm tạo và hàm thuộc tính như một lớp thông thường:

...

private Type expected = null;

private string msg = "";

public ExpectedExceptionAttribute(Type expectedType):this(expectedType, ""){}

public ExpectedExceptionAttribute(Type expectedType, string message){

if (expectedType as Exception == null)

throw ...

expected = expectedType;

msg = message;

}

public Type ExpectedType{

get{

return expected;

}

}

public string Message{

get{

return msg;

}

set{

msg = value;

}

}

...

Khi sử dụng, các tham biến của hàm tạo trở thành các tham số vị trí (tức là bắt buộc có và được truyền theo đúng thứ tự khai báo), còn các hàm thuộc tính trở thành tham số có tên (tức không bắt buộc có và có thể được truyền theo thứ tự tùy ý, miễn là phải sau các tham số vị trí). Sau đây là một số cách dùng hợp lệ:

[ExpectedException(typeof(Exception))]

[ExpectedException(typeof(Exception), "Expected type: System.Exception")]

[ExpectedException(typeof(Exception), Message="Expected type: System.Exception")]

[ExpectedException(typeof(Exception), "Expected type: System.Exception"), Message="Expected type: System.Exception")]

Thuộc tính của ta chỉ cần áp dụng cho hàm tạo, hàm chức năng, hàm thuộc tính. Do đó, ta cần chỉ định mục tiêu áp dụng cho nó thông qua thuộc tính AttributeUsage như sau:

[AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property)]

public class ExpectedExceptionAttribute:System.Attribute{...}

Mặt khác, một hàm có thể phát ra nhiều lỗi khác nhau, tức là thuộc tính ExpectedException có thể áp dụng nhiều lần cho cùng một mục tiêu. Ta chỉ định thêm:

[AttributeUsage(..., AllowMultiple = true)]

Cuối cùng, ta muốn rằng nếu các hàm virtual của lớp A được áp dụng thuộc tính ExpectedException thì các hàm override tương ứng của lớp con của A cũng kế thừa thuộc tính này. Do đó ta thêm:

[AttributeUsage(..., ..., Inherited = true)]

Xin lưu ý là chỉ khi cả AllowMultiple và Inherited đều bằng true thì lớp con mới được kế thừa toàn bộ thuộc tính với cùng giá trị đã áp dụng cho lớp cha.

Đến đây coi như ta đã hoàn tất phần định nghĩa thuộc tính. Ta đặt thuộc tính vừa tạo vào assembly tên DemoAttrLib.dll. Tiếp đến, ta xây dựng một chương trình sử dụng ExpectedExceptionAttribute. Ta đặt chương trình này trong assembly DemoAttrClient.exe.

/* Chương trình này gồm 2 lớp là DemoParentClient và DemoChildClient */

using System;

using System.Reflection;

using DemoAttrLib;

namespace DemoAttrClient

{

public class DemoParentClient

{

[method:ExpectedException(typeof(TargetException))]

public DemoParentClient(){...}

[method:ExpectedException(typeof(ArgumentException))]

[method:ExpectedException(typeof(TargetException))]

public void TestMethod1() {...}

[method:ExpectedException(typeof(TargetException))]

public virtual void TestMethod2() {...}

}

class DemoChildClient:DemoParentClient

{

[method:ExpectedException(typeof(ArgumentException))]

public override void TestMethod2() {...}

[method:ExpectedException(typeof(ArgumentException))]

public new void TestMethod1() {...}

}

}

Như đã nói, một thuộc tính chỉ có giá trị khi một chương trình nào đó dùng đến nó. Chương trình này sẽ dùng các lớp trong không gian kiểu System.Reflection để kiểm tra các thuộc tính đi kèm từng phần tử trước khi ra quyết định xử lý thích hợp đối với phần tử đó. Dưới đây là một ví dụ đơn giản về chương trình như thế (trong assembly DemoAttrReader.exe):

/* Đây là chương trình loại Console dùng để liệt kê các hàm được áp dụng thuộc tính ExpectedException trong assembly chỉ định. */

using System;

using System.Reflection;

using DemoAttrLib;

namespace DemoAttrReader

{

class DemoReader

{

// Hàm này trả về một chuỗi chứa thông tin báo cáo về mọi hàm được áp dụng thuộc tính ExpectedException trong assembly chỉ định.

public static string Read(string assemblyName)

{...}

// Hàm này trả về một chuỗi chứa thông tin báo cáo về mọi hàm được áp dụng thuộc tính ExpectedException trong kiểu chỉ định.

private static string AttrRead(Type t)

{...}

[STAThread]

static void Main(string[] args)

{

if (args.Length != 1)

{

Console.WriteLine("Hay chi dinh mot assembly nao do.");

return;

}

Console.WriteLine("BAO CAO:");

Console.WriteLine(DemoReader.Read(args[0]));

}

}

}

Kết quả chạy chương trình như ở hình 4- (chú ý là có tới 2 hàm TestMethod1 đối với lớp DemoChildClient):

Hình 4

Nếu bạn muốn có một ví dụ phức tạp hơn, mời bạn tham khảo mã nguồn của NUnit (www.nunit.org), chương trình kiểm tra tự động khá thông dụng với các lập trình viên .NET. Cách hoạt động của NUnit đơn giản là: dò trong assembly chỉ định những lớp nào có thuộc tính TestFixture và kích hoạt những hàm được đánh dấu bằng thuộc tính Test, SetUp, TearDown,... trong các lớp ấy.

Vậy là chúng ta đã cơ bản tìm hiểu xong về thuộc tính của .NET. Hy vọng những điều vừa trình bày sẽ giúp ích cho các bạn trong công việc lập trình của mình.

Nguyên Phương

Email: [email protected]

10 công cụ miễn phí tốt nhất cho .NET12/7/2004 9:58:00 AM

Không thể có ứng dụng tốt nếu không có công cụ phát triển tốt, dù là phát triển với bất kỳ ngôn ngữ (lập trình) nào, ngay cả với các ngôn ngữ 'mạnh' của nền tảng .NET hiện đang 'nổi đình nổi đám'. Ngoài công cụ phát triển ứng dụng 'chính thống' và 'đồ sộ' như Visual Studio .NET (VS.NET) của Microsoft, cộng đồng phát triển .NET hiện nay có thêm nhiều lựa chọn với các công cụ gọn nhẹ hơn và đặc biệt là có mã nguồn mở hay miễn phí.

Bài viết này giới thiệu 10 công cụ miễn phí tốt nhất dành cho các nhà phát triển .NET, trong số đó có những công cụ giúp phát triển ứng dụng nhanh hơn và có những công cụ có thể làm thay đổi hẳn cách thức bạn viết mã lệnh (code).

SNIPPET COMPILER

Snippet Compiler (http://www.sliver.com/dotnet/SnippetCompiler) là công cụ dùng để viết code, biên dịch và chạy, nó đặc biệt có ích đối với những đoạn code nhỏ (khi bạn không muốn tạo toàn bộ project VS.NET cùng với các tập tin đi kèm).

Ví dụ, đoạn code dưới đây gọi chạy một ứng dụng khác (Notepad) từ .NET. Bạn có thể thực thi (chạy) đoạn code này ngay trong Snippet Compiler (chỉ việc nhấn nút Play).

using System;

using System.Collections;

public class MyClass {

public static void Main() {

System.Diagnostics.Process proc = new System.Diagnostics.Process();

proc.StartInfo.FileName= 'notepad.exe';

proc.Start();

proc.WaitForExit();

}

}

REGULATOR

Regulator (http://royo.is-a-geek.com/regulator) là công cụ hoàn chỉnh dùng để biên dịch và kiểm tra biểu thức chuỗi, đây là vấn đề hiện được quan tâm vì được ứng dụng nhiều trong .NET. Biểu thức chuỗi được dùng để định nghĩa các chuỗi ký tự và số, thường được dùng để so trùng dữ liệu người dùng nhập vào hay để tìm chuỗi ký tự trong một chuỗi lớn hơn.

Regulator cho phép bạn nhập vào một biểu thức chuỗi và dữ liệu đầu vào để kiểm tra. Bằng cách này bạn có thể thấy cách thức làm việc của biểu thức và kết quả trả về trước khi thực hiện trong ứng dụng.

Một trong những đặc tính hấp dẫn nhất của Regulator là khả năng tìm thư viện biểu thức trực tuyến ở regexlib.com. Ví dụ, nếu nhập vào chuỗi 'phone' trong ô tìm kiếm, bạn sẽ tìm thấy hơn 20 biểu thức khác nhau so khớp số điện thoại, bao gồm các biểu thức áp dụng cho số điện thoại ở Anh, Úc...

CODESMITH

CodeSmith (http://ericjsmith.net/codesmith) là công cụ sinh mã dựa trên template (mẫu có sẵn) dùng cú pháp tương tự như ASP.NET để sinh ra dạng code hay text bất kỳ, từ tập hàm đơn giản đến toàn bộ ứng dụng. Không giống như nhiều công cụ sinh mã khác, CodeSmith không yêu cầu bạn mô tả thiết kế hay kiến trúc ứng dụng.

Khi xây dựng ứng dụng, bạn nhận thấy thường phải lặp đi lặp lại một số công việc, ví dụ như viết code truy cập dữ liệu hay xây dựng hàm. CodeSmith đặc biệt hữu dụng trong những tình huống như vậy, vì nó cho phép bạn tạo các template để thực hiện tự động các công việc này, không chỉ cải thiện hiệu suất làm việc mà còn tránh cho bạn sự nhàm chán.

CodeSmith có sẵn một số template, bao gồm các kiểu tập hợp .NET cũng như thủ tục, nhưng sức mạnh thực sự của công cụ này chính là khả năng tạo template riêng.

Template của CodeSmith là tập tin văn bản đơn thuần và bạn có thể tạo bằng công cụ soạn thảo văn bản bất kỳ, chỉ với yêu cầu là lưu lại với đuôi .cst. Đầu tiên, bạn tạo phần đầu khai báo ngôn ngữ dùng cho template, ngôn ngữ kết quả và mô tả vắn tắt template.

<%@ CodeTemplate Language='C#'

TargetLanguage='C#'

Description='Car Template' %>

Phần kế tiếp của template khai báo các thuộc tính sẽ được xác định khi template chạy. Ví dụ dưới đây khai báo một thuộc tính chuỗi (string).

<%@ Property Name='ClassName' Type='String' Category='Context'

Description='Class Name' %>

Bước tiếp theo xây dựng phần thân template với mã lệnh tương tự ASP.NET, bạn có thể dùng bất kỳ lệnh .NET nào.

CodeSmith khá dễ dùng và có thể cho ra những kết quả tuyệt vời nếu được sử dụng đúng đắn. Một trong những phần phổ biến nhất của ứng dụng thích hợp cho việc sinh mã là truy cập dữ liệu. CodeSmith có tích hợp thành phần đặc biệt gọi là SchemaExplorer có thể dùng để sinh các template cho bảng dữ liệu (table), thủ tục lưu trữ (stored procedure) và gần như bất kỳ đối tượng SQL Server.

NUNIT

NUnit (hhtp://www.nunit.org) là khung kiểm tra đơn vị chương trình (như lớp, hàm hay module) có mã nguồn mở. Được phát triển theo mô hình JUnit (công cụ kiểm tra nổi tiếng dùng cho Java), nhưng NUnit được viết bằng C# và khai thác được ưu điểm của các ngôn ngữ .NET.

NUnit cho phép bạn viết hàm kiểm tra lỗi (unit test) theo ngôn ngữ lựa chọn để kiểm tra một chức năng cụ thể của chương trình. Unit test là cách thức tốt để kiểm tra hoạt động của đoạn code viết mới, và cũng là một phương thức kiểm tra hồi quy ứng dụng. Các unit test có thể lưu lại và chạy lại mỗi khi bạn sửa đổi code, điều này giúp phát hiện lỗi dễ dàng hơn và đảm bảo phát triển ứng dụng tốt hơn.

NUnit cung cấp khung để viết các unit test, và còn có giao diện đồ họa để chạy các unit test và xem kết quả. Ví dụ, chúng ta sẽ kiểm tra hoạt động của lớp Hashtable trong .NET với việc thêm vào và lấy ra 2 đối tượng. Bước đầu tiên là tham chiếu đến NUnit.Framework để có thể dùng các thuộc tính và hàm của NUnit; kế tiếp, tạo một lớp và đánh dấu nó với thuộc tính [TestFixture] để NUnit biết lớp này có hàm kiểm tra.

using System;

using System.Collections;

using NUnit.Framework;

namespace NunitExample {

[TestFixture]

public class HashtableTest {

public HashtableTest() { }

}

}

Kế tiếp, chúng ta tạo một hàm và đánh dấu với thuộc tính [Test] để NUnit biết đây là hàm kiểm tra. Trong hàm này chúng ta sẽ thiết lập Hashtable và đưa vào 2 giá trị, sau đó dùng hàm Assert.AreEqual để truy xuất 2 giá trị này.

[Test]

public void HashtableAddTest(){

Hashtable ht = new Hashtable();

ht.Add('Key1', 'Value1');

ht.Add('Key2', 'Value2');

Assert.AreEqual('Value1', ht['Key1'], 'Wrong object returned!');

Assert.AreEqual('Value2', ht['Key2'], 'Wrong object returned!');

}

Để chạy thủ tục kiểm tra, bạn cần xây dựng project, mở nó trong NUnit và nhấn nút Run. Bạn cũng có thể tải về NUnit Visual Studio .NET add-in (http://sourceforge.net/project/nunitaddin) để chạy kiểm tra trực tiếp trong Visual Studio.

FXCOP

FxCop (http://www.gotdotnet.com/team/fxcop) là công cụ kiểm tra gói chương trình đảm bảo tính tương thích với những quy tắc của .NET Framework (http://msdn.microsoft.com/library/default.asp?url=/library/en-

us/cpgenref/html/cpconnetframeworkdesignguidelines.asp): Thiết kế thư viện, vấn đề bản địa, quy cách đặt tên, hiệu suất, bảo mật. FxCop do Microsoft phát triển và kèm theo tập các quy tắc do Mircosoft đưa ra, tuy nhiên bạn có thể tạo thêm những quy tắc riêng.

Ví dụ, chúng ta hãy xem FxCop kiểm tra và phát hiện lỗi trong gói NUnitExample ở trên. Trước hết, bạn cần tạo một project FxCop và đưa vào gói mà bạn muốn kiểm tra, sau đó nhấn Analyze và FxCop sẽ kiểm tra và đưa ra thông báo lỗi (Hình 3).

FxCop có thể giúp bạn viết code tốt hơn nhưng nó không thể sửa chữa thiết kế tồi hay lập trình kém. FxCop cũng không thể thay thế việc kiểm tra code nhưng nó cho phép bạn dành nhiều thời gian hơn cho những vấn đề quan trọng hơn là quy ước đặt tên.

.NET REFLECTOR

.NET Reflector (http://aisto.com/roeder/dotnet) là công cụ 'dịch ngược' (decompiler) và duyệt danh sách lớp, có thể giúp bạn khám phá tất cả 'bí mật' bên trong một gói. .NET Framework đưa ra reflection dùng để xem code .NET bất kỳ, dù là lớp đơn hay toàn bộ gói chương trình ('reflection' là tính năng cho phép ứng dụng truy vấn siêu dữ liệu của chính nó). Reflection cũng có thể dùng để truy xuất thông tin từ các lớp, hàm và thuộc tính khác nhau trong một gói nào đó. .NET Reflector cho phép bạn duyệt danh sách các lớp và hàm trong một gói, bạn có thể xem xét ngôn ngữ trung gian của Microsoft (MSIL) được sinh ra từ các lớp và hàm này, và có thể dịch ngược các lớp và hàm sang C# hay VB.NET.

Ví dụ, chúng ta dùng .NET Reflector xem xét gói NUnitExample ở trên, hình 4 thể hiện gói này khi được nạp. Để xem MSIL của một hàm, bạn nhấn chọn hàm và chọn menu Disassembler, hay chọn menu Decompiler để xem ở dạng ngôn ngữ C#. Bạn cũng có thể dịch ngược hàm sang VB.NET hay Delphi bằng cách thay đổi tùy chọn trong menu Language.

.NET Reflector đặc biệt có ích để tìm hiểu các hàm và gói trong .NET Framework. Ví dụ, dùng .NET Reflector bạn có thể biết được cách thức mà Microsoft dùng với hàm ReadXml. .NET Reflector cũng rất có ích để tìm hiểu cách thức tạo các đối tượng như HttpHandlers, và qua đó biết được cách thức mà nhóm phát triển của Microsoft đã xây dựng các đối tượng trong Framework.

NDOC

Việc lập tài liệu chương trình luôn là công việc khó gây hứng thú. Ở đây không nói về tài liệu thiết kế mà là tài liệu hàm và thuộc tính của lớp. Công cụ NDoc (http://ndoc.sourceforge.net) sẽ tự động sinh tài liệu cho chương trình của bạn bằng cách dùng reflection để truy vấn thư viện và dùng XML được sinh từ chú thích XML C#. Chú thích XML chỉ có hiệu lực cho C#, tuy nhiên công cụ VB.DOC (http://vb-doc.sourceforge.net) và VBCommenter của VS.NET Power Toy có thể thực hiện tương tự cho VB.NET. Ngoài ra, phiên bản kế tiếp của Visual Studio sẽ hỗ trợ nhiều ngôn ngữ hơn.

Đầu tiên, bạn dùng NDoc để sinh chú thích XML cho gói chương trình. Nhấn phải project và chọn Properties.Configuration Properties.Build, sau đó nhập vào đường dẫn nơi lưu tập tin XML trong tùy chọn XML Documentation File. Dưới đây là tài liệu của hàm trong ví dụ NUnit.

/// <summary>

/// This test adds a number of values to the Hashtable collection

/// and then retrieves those values and checks if they match.

/// </summary>

[Test]

public void HashtableAddTest(){

//Method Body Here

}

Tài liệu XML của hàm này sẽ được trích xuất ra và lưu lại trong tập tin XML.

<member name='M:NUnitExample.HashtableTest.HashtableAddTest'>

<summary>This test adds a number of values to the Hashtable collection

and then retrieves those values and checks if they match.</summary>

</member>

Sau khi sinh ra tập tin XML, bước kế tiếp nạp gói chương trình và tập tin XML vào NDoc để xử lý. Việc này được thực hiện đơn giản bằng cách mở NDoc và nhấn nút Add. Sau khi khai báo thuộc tính đầu ra, nhấn nút Generate để bắt đầu quá trình sinh tài liệu.

NANT

NAnt (http://nant.sourceforge.net), phiên bản .NET của Ant được hỗ trợ với dự án Jakarta (khá phổ tiếng trong cộng đồng phát triển Java), là công cụ cho phép dễ dàng tạo qui trình build (biên dịch và tích hợp ứng dụng) dựa trên XML. Khi có nhiều nhà phát triển cùng làm việc trên một dự án, bạn không thể phó thác việc build cho từng người, và chắc bạn cũng không muốn thực hiện build thủ công nhiều lần mỗi ngày. NAnt cho phép bạn build tự động toàn bộ ứng dụng, chép các tập tin, chạy các kiểm tra NUnit, gửi email và nhiều chức năng khác. NAnt dùng các tập tin XML để khai báo những tác vụ cần thực hiện trong quá trình build. Lưu ý là MSBuild, thành phần trong phiên bản mới Visual Studio 2005, có tính năng tương tự và có thể thay thế NAnt.

Ví dụ dưới đây là tập tin XML (có phần đuôi là .build) để biên dịch ứng dụng NUnitExample với NAnt.

<?xml version='1.0'?>

<project name='NUnit Example' default='build' basedir='.'>

<description> The NUnit Example Project </description>

<property name='debug' value='true'/>

<target name = 'build' description = 'compiles the source code'>

<csc target='library' output='.\bin\debug\NUnitExample.dll'

debug='${debug}'>

<references>

<includes name='C:\program files\NUnit

V2.1\bin\NUnit.Framework.dll' />

</references>

<sources>

<includes name='HashtableTest.cs'/>

</sources>

</csc> </target>

</project>

Tập tin XML này được lưu ở thư mục gốc của project NUnitExample. Bạn đến thư mục này và chạy nant.exe để biên dịch ứng dụng.

Tuy không dễ dàng như việc nhấn Build trong Visual Studio, nhưng NAnt là công cụ rất mạnh dùng để xây dựng qui trình build chạy tự động theo lịch biểu.

Công cụ chuyển đổi

Cuối cùng là 2 công cụ đơn giản nhưng rất hữu dụng. Đầu tiên là ASP.NET Version Switcher (http://www.denisbauer.com/NETTools/ASPNETVersionSwitcher.aspx), công cụ này dùng để chuyển đổi phiên bản (version) ASP.NET của một website đang hoạt động. Công cụ thứ hai là Visual Studio Converter (http://www.codeproject.com/macro/vsconvert.asp) dùng để chuyển đổi tập tin project từ VS.NET 2002 sang VS.NET 2003 hay ngược lại.

IIS sử dụng cơ chế ánh xạ phần mở rộng (extension) để xử lý yêu cầu một website. Khi cài ASP.NET 1.1, cơ chế này được nâng cấp phiên bản mới và gây lỗi khi chạy ứng dụng được xây dựng trên ASP.NET 1.0. Để giải quyết vấn đề này, bạn có thể chuyển tất cả ánh xạ phần mở rộng của website về phiên bản 1.0, tuy nhiên, thực hiện thủ công việc này rất vất vả và đây chính là nơi 'dụng võ' của ASP.NET Version Switcher. Tiện ích nhỏ này có thể dùng để chuyển version .NET của bất kỳ ứng dụng ASP.NET nào. Công cụ này càng có ích khi tương lai có thêm các phiên bản mới ASP.NET và .NET Framework.

Visual Studio Converter tương tự như ASP.NET Version Switcher, ngoại trừ việc nó được dùng để chuyển đổi version của tập tin project Visual Studio. Mặc dù chỉ có một ít khác biệt giữa .NET Framework version 1.0 và 1.1, một khi tập tin project được chuyển từ VS.NET 2002 sang VS.NET 2003 thì không thể chuyển ngược lại. Tuy nhiên, đôi khi việc chuyển ngược lại cần thiết. Công cụ Converter này cho phép chuyển bất kỳ tập tin solution hay project từ Visual Studio 7.1 (VS.NET 2003) về Visual Studio 7.0 (VS.NET 2002) và ngược lại.

Kết luận

Vậy là chúng ta đã 'cưỡi ngựa xem hoa' một số công cụ miễn phí tuyệt vời hỗ trợ cho việc phát triển trên nền .NET. Hy vọng trong số này có những công cụ đáp ứng nhu cầu của bạn và có thể giúp bạn cải thiện hiệu suất. Hãy trang bị đầy đủ các công cụ cần thiết, đó có thể là máy tính mạnh, Visual Studio phiên bản mới nhất hay tiện ích miễn phí vì chúng sẽ giúp tạo nên sự khác biệt cho bạn.

Bạn đang đọc truyện trên: Truyen2U.Pro

#dot#net