1. Trang chủ >
  2. Công Nghệ Thông Tin >
  3. Kỹ thuật lập trình >

12 Tạo một đối tượng bằng cơ chế phản chiếu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (4.45 MB, 563 trang )


90

Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu







Thu lấy đối tượng Type mô tả kiểu của đối tượng cần tạo, gọi phương thức

GetConstructor của nó để có được đối tượng System.Reflection.ConstructorInfo

mô tả phương thức khởi dựng cần dùng, sau đó thực thi phương thức

ConstructorInfo.Invoke.



Bước đầu tiên trong việc tạo một đối tượng bằng cơ chế phản chiếu là thu lấy đối tượng Type

mô tả kiểu của đối tượng cần tạo (xem mục 3.10 để biết thêm chi tiết). Khi có được đối tượng

Type, hãy gọi phương thức GetConstructor để thu lấy đối tượng ConstructorInfo mô tả một

trong các phương thức khởi dựng của kiểu này. Dạng thức thông dụng nhất của phương thức

GetConstructor là nhận một mảng Type làm đối số, và trả về đối tượng ConstructorInfo mô

tả phương thức khởi dựng nhận các đối số được chỉ định trong mảng Type. Để thu lấy đối

tượng ConstructorInfo mô tả phương thức khởi dựng mặc định (không có đối số), bạn hãy

truyền cho phương thức GetConstructor một mảng Type rỗng (sử dụng trường tĩnh

Type.EmptyTypes); đừng sử dụng null, nếu không GetConstructor sẽ ném ngoại lệ

System.ArgumentNullException. Nếu GetConstructor không tìm thấy phương thức khởi dựng

nào có chữ ký phù hợp với các đối số được chỉ định thì nó sẽ trả về null.

Môt khi đã có đối tượng ConstructorInfo như mong muốn, hãy gọi phương thức Invoke của

nó. Bạn phải cung cấp một mảng chứa các đối số mà bạn muốn truyền cho phương thức khởi

dựng. Phương thức Invoke sẽ tạo đối tượng mới và trả về một tham chiếu đến đối tượng đó

(bạn phải ép về kiểu phù hợp). Dưới đây là đoạn mã trình bày cách tạo một đối tượng

System.Text.StringBuilder, chỉ định nội dung ban đầu cho StringBuilder và sức chứa của

nó.

// Thu lấy đối tượng Type cho lớp StringBuilder.

Type type = typeof(System.Text.StringBuilder);

// Tạo Type[] chứa các đối tượng Type cho mỗi đối số

// của phương thức khởi dựng (một chuỗi và một số nguyên).

Type[] argTypes = new Type[] {typeof(System.String),

typeof(System.Int32)};

// Thu lấy đối tượng ConstructorInfo.

ConstructorInfo cInfo = type.GetConstructor(argTypes);

// Tạo object[] chứa các đối số cho phương thức khởi dựng.

object[] argVals = new object[] {"Some string", 30};

// Tạo đối tượng và ép nó về kiểu StringBuilder.

StringBuilder sb = (StringBuilder)cInfo.Invoke(argVals);



Chức năng phản chiếu thường được sử dụng để hiện thực các factory. Trong đó, bạn sử dụng

cơ chế phản chiếu để thể hiện hóa các lớp thừa kế một lớp cơ sở phổ biến hay hiện thực một

giao diện phổ biến. Thông thường, cả lớp cơ sở chung và giao diện chung đều được sử dụng.

Lớp cơ sở trừu tượng sẽ hiện thực giao diện và bất kỳ chức năng chung nào, sau đó mỗi hiện

thực cụ thể sẽ thừa kế lớp cơ sở.

Không có cơ chế nào để khai báo rằng mỗi lớp cụ thể phải hiện thực các phương thức khởi

dựng với các chữ ký cụ thể. Nếu muốn người khác (hãng thứ ba) hiện thực các lớp cụ thể thì

bạn phải chỉ rõ (trong tài liệu hướng dẫn) chữ ký của phương thức khởi dựng mà factory của

bạn gọi. Cách thông thường để tránh vấn đề này là sử dụng phương thức khởi dựng mặc định

(không có đối số), sau đó cấu hình đối tượng bằng phương thức và thuộc tính. Ví dụ dưới đây

sẽ hiện thực một factory dùng để tạo các đối tượng có hiện thực giao diện IPlugin.



91

Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu

using System;

using System.Reflection;

// Giao diện chung mà tất cả các plug-in phải hiện thực.

public interface IPlugin {

string Description { get; set; }

void Start();

void Stop();

}

// Lớp cơ sở trừu tượng mà tất cả các plug-in phải dẫn xuất từ đây.

public abstract class AbstractPlugin : IPlugin {

// Chuỗi chứa lời mô tả plug-in.

private string description = "";

// Thuộc tính dùng để lấy lời mô tả plug-in.

public string Description {

get { return description; }

set { description = value; }

}



}



// Khai báo các thành viên của giao diện IPlugin.

public abstract void Start();

public abstract void Stop();



// Một hiện thực đơn giản cho giao diện IPlugin

// để minh họa lớp PluginFactory.

public class SimplePlugin : AbstractPlugin {

// Hiện thực phương thức Start.

public override void Start() {

Console.WriteLine(Description

}



+ ": Starting...");



// Hiện thực phương thức Stop.

public override void Stop() {

Console.WriteLine(Description + ": Stopping...");

}

}

// Factory dùng để tạo các đối tượng của IPlugin.

public sealed class PluginFactory {

public static IPlugin CreatePlugin(string assembly,

string pluginName, string description) {

// Thu lấy đối tượng Type cho plug-in được chỉ định.

Type type = Type.GetType(pluginName + ", " + assembly);

// Thu lấy đối tượng ConstructorInfo.

ConstructorInfo cInfo = type.GetConstructor(Type.EmptyTypes);

// Tạo đối tượng và ép nó về kiểu StringBuilder.

IPlugin plugin = (IPlugin)cInfo.Invoke(null);

// Cấu hình IPlugin mới.

plugin.Description = description;

}



return plugin;



}



Câu lệnh sau đây sẽ tạo đối tượng SimplePlugin bằng lớp PluginFactory:



92

Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu

IPlugin plugin = PluginFactory.CreatePlugin(

"CreateObjectExample", // Tên assembly

"SimplePlugin",

// Tên lớp plug-in

"A Simple Plugin"

// Lời mô tả plug-in

);







Lớp System.Activator cung cấp hai phương thức tĩnh CreateInstance và

CreateInstanceFrom dùng để tạo các đối tượng dựa trên đối tượng Type hay chuỗi

chứa tên kiểu. Xem tài liệu .NET Framework SDK để biết thêm chi tiết.



13







Tạo một đặc tính tùy biến

Bạn cần tạo ra một đặc tính theo ý bạn.

Tạo một lớp dẫn xuất từ lớp cơ sở trừu tượng System.Attribute. Hiện thực các

phương thức khởi dựng, các trường, và các thuộc tính để cho phép người dùng

cấu hình đặc tính. Sử dụng System.AttributeUsageAttribute để định nghĩa:

• Những phần tử chương trình nào là đích của đặc tính

• Bạn có thể áp dụng nhiều thể hiện của đặc tính cho một phần tử chương

trình hay không

• Đặc tính có được thừa kế bởi các kiểu dẫn xuất hay không



Đặc tính cung cấp một cơ chế tổng quát cho việc kết hợp thông tin khai báo (siêu dữ liệu) với

các phần tử chương trình. Siêu dữ liệu này nằm trong assembly đã được biên dịch, cho phép

các chương trình thu lấy nó thông qua cơ chế phản chiếu lúc thực thi (xem mục 3.14.) Các

chương trình khác, đặc biệt là CLR, sử dụng thông tin này để xác định cách thức tương tác và

quản lý các phần tử chương trình.

Để tạo một đặc tính tùy biến thì hãy dẫn xuất một lớp từ lớp cơ sở trừu tượng

System.Attribute. Các lớp đặc tính tùy biến phải là public và có tên kết thúc bằng

“Attribute”. Một đặc tính tùy biến phải có ít nhất một phương thức khởi dựng công khai.

Các đối số của phương thức khởi dựng sẽ trở thành các đối số vị trí (positional parameter)

của đặc tính. Như với bất kỳ lớp nào khác, bạn có thể khai báo nhiều phương thức khởi dựng,

cho phép người dùng tùy chọn sử dụng các tập khác nhau của các đối số vị trí khi áp dụng đặc

tính. Bất kỳ thuộc tính và trường đọc/ghi công khai nào do đặc tính khai báo đều trở thành đối

số được nêu tên (named parameter).

Để điều khiển cách thức người dùng áp dụng đặc tính, hãy áp dụng đặc tính

AttributeUsageAttribute cho đặc tính tùy biến của bạn. Đặc tính AttributeUsageAttribute

hỗ trợ một đối số vị trí và hai đối số được nêu tên, được mô tả trong bảng 3.3. Các giá trị mặc

định chỉ định giá trị sẽ được áp dụng cho đặc tính tùy biến của bạn nếu bạn không áp dụng

AttributeUsageAttribute hoặc không chỉ định giá trị cho một thông số.

Bảng 3.3 Các thành viên thuộc kiểu liệt kê AttributeUsage

Thông số



Kiểu



Mô tả



Mặc định



93

Chương 3: Miền ứng dụng, cơ chế phản chiếu, và siêu dữ liệu



vị trí



Một thành viên thuộc kiểu liệt kê

System.AttributeTargets, chỉ định

phần tử chương trình mà đặc tính sẽ

có hiệu lực trên đó.



AttributeTargets.All



AllowMultiple



được nêu

tên



Đặc tính có thể được chỉ định nhiều

lần cho một phần tử hay không.



false



Inherited



được nêu

tên



Đặc tính có được thừa kế bởi các lớp

dẫn xuất hay các thành viên được

chép đè hay không.



true



ValidOn



Ví dụ dưới đây trình bày cách tạo một đặc tính tùy biến có tên là AuthorAttribute, cho phép

bạn xác định tên và công ty của người tạo ra lớp hay assembly. AuthorAttribute khai báo

một phương thức khởi dựng công khai, nhận một chuỗi chứa tên tác giả. Điều này yêu cầu

người sử dụng AuthorAttribute phải luôn cung cấp một đối số vị trí chứa tên tác giả. Company

là thuộc tính công khai (có thể dùng làm đối số được nêu tên), Name là thuộc tính chỉ-đọc

(không thể dùng làm đối số được nêu tên).

using System;

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly,

AllowMultiple = true, Inherited = false)]

public class AuthorAttribute : System.Attribute {

private string company; // Công ty của tác giả

private string name;

// Tên tác giả

// Khai báo phương thức khởi dựng công khai.

public AuthorAttribute(string name) {

this.name = name;

company = "";

}

// Khai báo thuộc tính Company có quyền set/get.

public string Company {

get { return company; }

set { company = value; }

}



}



// Khai báo thuộc tính Name chỉ-đọc.

public string Name{

get { return name;}

}



Dưới đây là cách sử dụng AuthorAttribute:

// Khai báo Square Nguyen là tác giả của assembly.

[assembly:Author("Square Nguyen", Company = "Goldsoft Ltd.")]

// Khai báo Square Nguyen là tác giả của lớp.

[Author("Square Nguyen", Company = "Goldsoft Ltd.")]

public class SomeClass {

§

}



Xem Thêm
Tải bản đầy đủ (.doc) (563 trang)

×