1. Trang chủ
  2. » Công Nghệ Thông Tin

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

8 439 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Miền ứng dụng, cơ chế phản chiếu và siêu dữ liệu phần 3
Định dạng
Số trang 8
Dung lượng 175,14 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Trong khi miền ứng dụng đang được giải phóng, CLR gọi thực thi các phương thức giải phóng của tất cả các đối tượng trong miền ứng dụng.. Phương thức AppDomain.IsFinalizingForUnload trả

Trang 1

1.1 Giải phóng assembly và miền ứng dụng

V Bạn cần giải phóng các assembly hay các miền ứng dụng lúc thực thi

# Không có cách nào để giải phóng các assembly riêng lẻ Bạn có thể giải phóng

toàn bộ một miền ứng dụng bằng phương thức tĩnh AppDomain.Unload, đồng

thời với việc giải phóng miền ứng dụng là tất cả các assembly đã được nạp vào

miền ứng dụng đó cũng được giải phóng

Cách duy nhất để giải phóng một assembly là giải phóng cả miền ứng dụng mà nó đã

được nạp vào Đáng tiếc, việc giải phóng một miền ứng dụng cũng sẽ giải phóng luôn tất

cả các assembly đã được nạp vào đó Đây là một giới hạn yêu cầu bạn phải tổ chức và

quản lý tốt cấu trúc miền ứng dụng và assembly

Khi giải phóng một miền ứng dụng bằng phương thức tĩnh AppDomain.Unload, bạn cần

truyền cho nó một tham chiếu AppDomain đến miền ứng dụng cần giải phóng Bạn

không thể giải phóng miền ứng dụng mặc định do CLR tạo lúc startup Đoạn mã dưới đây

trình bày cách sử dụng phương thức Unload

// Tạo một miền ứng dụng mới

AppDomain newDomain = AppDomain.CreateDomain("New Domain");

// Nạp assembly vào miền ứng dụng mày

§

// Giải phóng miền ứng dụng

AppDomain.Unload(newDomain);

Phương thức Unload chặn các tiểu trình mới đi vào miền ứng dụng được chỉ định và gọi

phương thức Thread.Abort trên tất cả các tiểu trình hiện đang chạy trong miền ứng dụng

này Nếu tiểu trình gọi phương thức Unload hiện đang chạy trong miền ứng dụng cần giải

phóng thì một tiểu trình khác sẽ được khởi chạy để thực hiện quá trình giải phóng Nếu

có vấn đề trong việc giải phóng miền ứng dụng, ngoại lệ

System.CannotUnloadAppDomainException sẽ bị ném bởi tiểu trình thực hiện quá trình

giải phóng

Trong khi miền ứng dụng đang được giải phóng, CLR gọi thực thi các phương thức giải

phóng của tất cả các đối tượng trong miền ứng dụng Tùy thuộc vào số lượng đối tượng

và bản chất của các phương thức giải phóng mà quá trình này có thể mất một khoảng thời

gian nào đó Phương thức AppDomain.IsFinalizingForUnload trả về true nếu miền ứng

dụng đang được giải phóng và CLR đã bắt đầu giải phóng các đối tượng trong đó; ngược

lại, trả về false

Trang 2

V Bạn muốn thu lấy đối tượng System.Type mô tả một kiểu dữ liệu nhất định

# Sử dụng một trong các cách sau:

• Toán tử typeof

• Phương thức tĩnh GetType của lớp System.Type

• Phương thức GetType thuộc một thể hiện của kiểu

• Phương thức GetNestedType hay GetNestedTypes của lớp Type

• Phương thức GetType hay GetTypes của lớp Assembly

• Phương thức GetType, GetTypes, hay FindTypes của lớp System.Reflection

Module

Đối tượng Type cung cấp một điểm khởi đầu để làm việc với các kiểu dữ liệu bằng cơ chế phản chiếu Một đối tượng Type cho phép bạn kiểm tra siêu dữ liệu của kiểu, thu lấy

các thành viên của kiểu, và tạo các đối tượng của kiểu Do tầm quan trọng của nó, NET

Framework cung cấp nhiều cơ chế để lấy tham chiếu đến các đối tượng Type

Phương pháp hiệu quả nhất để thu lấy đối tượng Type cho một kiểu cụ thể là sử dụng toán tử typeof:

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

Tên kiểu không được đặt trong dấu nháy kép và phải khả phân giải đối với trình biên dịch Vì tham chiếu được phân giải lúc biên dịch nên assembly chứa kiểu này trở thành phần phụ thuộc tĩnh của assembly và sẽ được liệt kê như thế trong assembly manifest của bạn

Một cách khác là sử dụng phương thức tĩnh Type.GetType, nhận vào một chuỗi chứa tên kiểu Vì sử dụng chuỗi để chỉ định kiểu nên bạn có thể thay đổi nó lúc thực thi, điều này

mở ra cánh cửa đến với thế giới lập trình động bằng cơ chế phản chiếu (xem mục 3.12) Nếu bạn chỉ định tên kiểu, bộ thực thi phải tìm kiểu này trong một assembly đã được nạp

Bạn cũng có thể chỉ định một tên kiểu theo tiêu chuẩn assembly (tham khảo tài liệu NET

Framework SDK về phương thức Type.GetType để biết cách kết cấu tên kiểu theo tiêu

chuẩn assembly) Các lệnh sau trình bày cách sử dụng phương thức GetType:

// Có phân biệt chữ hoa-thường, trả về null nếu không tìm thấy

Type t2 = Type.GetType("System.String");

// Có phân biệt chữ hoa-thường,

// ném ngoại lệ TypeLoadException nếu không tìm thấy

Type t3 = Type.GetType("System.String", true);

// Không phân biệt chữ hoa-thường,

// ném ngoại lệ TypeLoadException nếu không tìm thấy

Type t4 = Type.GetType("system.string", true, true);

Trang 3

// Tên kiểu theo tiêu chuẩn assembly

Type t5 = Type.GetType("System.Data.DataSet,System.Data," +

"Version=1.0.5000.0,Culture=neutral,

PublicKeyToken=b77a5c561934e089");

Để thu lấy đối tượng Type mô tả kiểu của một đối tượng hiện có, hãy sử dụng phương thức GetType, được hiện thực bởi Object và được thừa kế bởi tất cả các kiểu dữ liệu Dưới đây là một ví dụ:

System.Text.StringBuilder sb = new System.Text.StringBuilder();

Type t6 = sb.GetType();

Bảng 3.2 tóm tắt các phương thức khác cũng cung cấp khả năng truy xuất đối tượng Type

Bảng 3.2 Các phương thức trả về đối tượng Type

Phương thức Mô tả

Type.GetNestedType Lấy đối tượng Type mô tả một kiểu lồng bên trong

đối tượng Type hiện có Type.GetNestedTypes Lấy một mảng các đối tượng Type mô tả các kiểu

lồng bên trong đối tượng Type hiện có Assembly.GetType Lấy đối tượng Type mô tả một kiểu được khai báo

bên trong assembly Assembly.GetTypes Lấy một mảng các đối tượng Type mô tả các kiểu được khai báo bên trong assembly

Module.GetType Lấy đối tượng Type mô tả một kiểu được khai báo

bên trong module Module.GetTypes Lấy một mảng các đối tượng Type mô tả các kiểu

được khai báo bên trong module

Module.FindTypes

Lấy một mảng đã được lọc, chứa các đối tượng Type mô tả các kiểu được khai báo bên trong

module—các kiểu này được lọc bằng một delegate

(xác định xem mỗi Type có xuất hiện trong mảng đích hay không)

1.3 Kiểm tra kiểu của một đối tượng

V Bạn muốn kiểm tra kiểu của một đối tượng

Trang 4

# Sử dụng phương thức thừa kế Object.GetType để thu lấy Type cho đối tượng này Trong vài trường hợp, bạn cũng có thể sử dụng toán tử is và as để kiểm tra kiểu của một đối tượng

Tất cả các kiểu dữ liệu đều thừa kế phương thức GetType từ lớp cơ sở Object Như đã được thảo luận trong mục 3.10, phương thức này trả về một tham chiếu Type mô tả kiểu của đối tượng Bộ thực thi duy trì một đối tượng Type cho mỗi kiểu được nạp và tất cả các tham chiếu cho kiểu này cùng chỉ đến đối tượng này Điều này nghĩa là bạn có thể so sánh hai tham chiếu kiểu một cách hiệu quả Ví dụ dưới đây trình bày cách kiểm tra một đối tượng có phải là System.IO.StringReader hay không:

// Tạo một StringReader để thử nghiệm

Object someObject =

new StringReader("This is a StringReader");

// Kiểm tra xem someObject có phải là một StringReader hay không

// bằng cách thu lấy và so sánh tham chiếu Type (sử dụng toán tử typeof)

if (typeof(System.IO.StringReader) == someObject.GetType()) {

// Làm gì đó

§

}

C# cung cấp toán tử is để thực hiện nhanh việc kiểm tra như trên Ngoài ra, is sẽ trả về

true nếu đối tượng cần kiểm tra dẫn xuất từ lớp được chỉ định Đoạn mã dưới đây kiểm tra xem someObject là một thể hiện của System.IO.TextReader, hay một lớp dẫn xuất từ TextReader (như StringReader):

// Kiểm tra xem someObject là TextReader,

// hay dẫn xuất từ TextReader bằng toán tử is

if (someObject is System.IO.TextReader) {

// Làm gì đó

§

}

Cả hai cách này đều đòi hỏi kiểu dùng với toán tử typeof và is phải là kiểu đã biết và khả phân giải lúc biên dịch Một cách khác linh hoạt hơn (nhưng chậm hơn) là sử dụng phương thức Type.GetType để trả về một tham chiếu Type cho kiểu được chỉ định Tham chiếu Type không được phân giải cho đến khi thực thi, việc này ảnh hưởng đến hiệu năng, nhưng cho phép bạn thay đổi phép so sánh kiểu lúc thực thi dựa trên giá trị của một chuỗi Phương thức IsType dưới đây sẽ trả về true nếu đối tượng thuộc kiểu được chỉ định và sử dụng phương thức Type.IsSubclassOf để kiểm tra đối tượng này có phải là một lớp con của kiểu được chỉ định hay không

public static bool IsType(object obj, string type) {

Trang 5

Type t = Type.GetType(type, true, true);

return t == obj.GetType() || obj.GetType().IsSubclassOf(t);

}

Cuối cùng, bạn có thể sử dụng toán tử as để ép bất kỳ đối tượng nào sang kiểu được chỉ định Nếu đối tượng không thể bị ép sang kiểu được chỉ định, toán tử as sẽ trả về null

Điều này cho phép bạn thực hiện các phép ép kiểu an toàn (safe cast), nhưng kiểu được

so sánh phải là khả phân giải lúc thực thi Dưới đây là một ví dụ:

// Sử dụng toán tử as để thực hiện một phép ép kiểu an toàn

StringReader reader = someObject as System.IO.StringReader;

if (reader != null) {

// Làm gì đó

§

}

Í Phương thức tĩnh GetUnderlyingType của lớp System.Enum cho phép bạn thu lấy kiểu thực sự của một kiểu liệt kê

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

V Bạn cần tạo một đối tượng bằng cơ chế phản chiế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

Trang 6

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

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

Trang 7

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 {

Trang 8

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: IPlugin plugin = PluginFactory.CreatePlugin(

"CreateObjectExample", // Tên assembly

"SimplePlugin", // Tên lớp plug-in

"A Simple Plugin" // Lời mô tả plug-in

Ngày đăng: 24/10/2013, 05:15

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w