lớp .NET Framework cung cấp các hiện thực formatter sau đây để tuần tự hóa đối tượng theo dạng nhị phân hay SOAP: • System.Runtime.Serialization.Formatters.Binary.BinaryFormatter • Syste
Trang 1this.List.Remove(value);
}
public AssemblyName this[int index] {
get {
return (AssemblyName)this.List[index];
}
set {
this.List[index] = value;
}
}
public bool Contains(AssemblyName value) {
return this.List.Contains(value);
}
public void Insert(int index, AssemblyName value) {
this.List.Insert(index, value);
}
}
Cả hai lớp CollectionBase và DictionaryBase đều hiện thực một tập các phương thức được-bảo-vệ có tiếp đầu ngữ On* Các phương thức này (chẳng hạn OnClear, OnClearComplete,
OnGet, OnGetComplete,…) thường được chép đè ở các lớp dẫn xuất nhằm cho phép bạn hiện thực các chức năng tùy biến cần thiết để quản lý tập hợp kiểu mạnh Các lớp CollectionBase
và DictionaryBase sẽ gọi phương thức phù hợp trước và sau khi việc chỉnh sửa được thực hiện trên tập hợp nằm dưới thông qua thuộc tính List hay Dictionary
12. L u m t đ i t L u m t đ i t ư ộ ố ượ ư ộ ố ượ ng kh -tu n-t -hóa vào file ng kh -tu n-t -hóa vào file ả ầ ự ả ầ ự
Bạn cần lưu một đối tượng khả-tuần-tự-hóa và các trạng thái của nó vào file, sau
đó giải tuần tự hóa khi cần.
Sử dụng một formatter để tuần tự hóa đối tượng và ghi nó vào một
System.IO.FileStream Khi cần truy xuất đối tượng, sử dụng formatter cùng kiểu
để đọc dữ liệu được-tuần-tự-hóa từ file và giải tuần tự hóa đối tượng Thư viện
Trang 2lớp NET Framework cung cấp các hiện thực formatter sau đây để tuần tự hóa đối tượng theo dạng nhị phân hay SOAP:
• System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
• System.Runtime.Serialization.Formatters.Soap.SoapFormatter
Lớp BinaryFormatter và SoapFormatter có thể được sử dụng để tuần tự hóa một đối tượng của bất kỳ kiểu nào được gắn với đặc tính System.SerializableAttribute BinaryFormatter
sinh ra một stream dữ liệu nhị phân mô tả đối tượng và trạng thái của nó, trong khi
SoapFormatter sinh ra một tài liệu SOAP.
Cả hai lớp BinaryFormatter và SoapFormatter đều hiện thực giao diện System.Runtime Serialization.IFormatter, giao diện này định nghĩa hai phương thức: Serialize và
Deserialize
• Serialize nhận một tham chiếu System.Object và một tham chiếu System.IO.Stream
làm đối số, tuần tự hóa Object và ghi nó vào Stream
• Deserialize nhận một tham chiếu Stream làm đối số, đọc dữ liệu của đối tượng được-tuần-tự-hóa từ Stream, và trả về một tham chiếu Object đến đối tượng được-giải-tuần-tự-hóa Bạn phải ép tham chiếu Object này về kiểu thích hợp
Để gọi các phương thức Serialize và Deserialize của lớp BinaryFormatter, mã lệnh của bạn phải được cấp phần tử SerializationFormatter của lớp System.Security.Permissions SecurityPermission
Để gọi các phương thức Serialize và Deserialize của lớp SoapFormatter, mã lệnh của bạn
phải được cấp quyền “tin tưởng tuyệt đối” (full trust) vì assembly System.Runtime
Serialization.Formatters.Soap.dll (lớp SoapFormatter được khai báo bên trong assembly này)
không cho phép các mã lệnh chỉ được-tin-cậy-một-phần (partially trusted caller) sử dụng nó
Tham khảo mục 13.1 để có thêm thông tin về mã lệnh được-tin-cậy-một-phần
Lớp BinarySerializationExample dưới đây minh họa cách sử dụng lớp BinaryFormatter để tuần tự hóa một System.Collections.ArrayList chứa danh sách tên người vào một file Sau
đó, ArrayList được giải tuần tự hóa từ file và nội dung của nó sẽ được hiển thị trong cửa sổ
Console.
using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;
public class BinarySerializationExample {
public static void Main() {
// Tạo và cấu hình ArrayList để tuần tự hóa.
ArrayList people = new ArrayList();
people.Add("Phuong");
Trang 3people.Add("Nam");
// Tuần tự hóa đối tượng ArrayList.
FileStream str = File.Create("people.bin");
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(str, people);
str.Close();
// Giải tuần tự hóa đối tượng ArrayList.
str = File.OpenRead("people.bin");
bf = new BinaryFormatter();
people = (ArrayList)bf.Deserialize(str);
str.Close();
// Hiển thị nội dung của đối tượng ArrayList
// đã-được-giải-tuần-tự-hóa.
foreach (string s in people) {
System.Console.WriteLine(s);
}
}
}
Bạn có thể sử dụng lớp SoapFormatter theo cách như được trình bày trong lớp
BinarySerializationExample ở trên, chỉ cần thay mỗi thể hiện của lớp BinaryFormatter bằng thể hiện của lớp SoapFormatter và thay đổi chỉ thị using để nhập không gian tên
System.Runtime.Serialization.Formatters.Soap Ngoài ra, bạn cần thêm một tham chiếu đến System.Runtime.Serialization.Formatters.Soap.dll khi biên dịch mã File
SoapSerializationExample.cs trong đĩa CD đính kèm sẽ trình bày cách sử dụng lớp
SoapFormatter
Hình 2.1 và 2.2 dưới đây minh họa hai kết quả khác nhau khi sử dụng lớp BinaryFormatter và
SoapFormatter Hình 2.1 trình bày nội dung của file people.bin được tạo ra khi sử dụng
BinaryFormatter, hình 2.2 trình bày nội dung của file people.xml được tạo ra khi sử dụng
SoapFormatter
Trang 4Hình 2.1 Nội dung file people.bin
Hình 2.2 Nội dung file people.xml
Trang 6Chương 3:MIỀN ỨNG DỤNG, CƠ CHẾ PHẢN CHIẾU, VÀ
SIÊU DỮ LIỆU
Trang 8ức mạnh và tính linh hoạt của Microsoft NET Framework được nâng cao bởi khả năng
kiểm tra và thao tác các kiểu và siêu dữ liệu lúc thực thi Các mục trong chương này sẽ
trình bày các khía cạnh thông dụng của miền ứng dụng (application domain), cơ chế phản chiếu (reflection), và siêu dữ liệu (metadata), bao gồm:
S
Tạo và hủy các miền ứng dụng (mục 3.1 và 3.9)
Làm việc với các kiểu và các đối tượng khi sử dụng nhiều miền ứng dụng (mục 3.2, 3.3, 3.4, và 3.8)
Làm việc với thông tin Type (mục 3.10 và 3.11)
Tạo động các đối tượng và nạp động các assembly lúc thực thi (mục 3.5, 3.6, 3.7, và 3.12)
Tạo và kiểm tra các đặc tính tùy biến (các mục 3.13 và 3.14)
1. T o mi n ng d ng T o mi n ng d ng ạ ạ ề ứ ề ứ ụ ụ
Bạn cần tạo một miền ứng dụng mới.
Sử dụng phương thức tĩnh CreateDomain của lớp System.AppDomain
Dạng thức đơn giản nhất của phương thức CreateDomain nhận một đối số kiểu string chỉ định tên thân thiện cho miền ứng dụng mới Các dạng thức khác cho phép bạn chỉ định chứng cứ
(evidence) và các thiết lập cấu hình cho miền ứng dụng mới Chứng cứ được chỉ định bằng đối
tượng System.Security.Policy.Evidence; mục 13.11 trình bày các tác động của chứng cứ khi bạn tạo một miền ứng dụng Các thiết lập cấu hình được chỉ định bằng đối tượng
System.AppDomainSetup
Lớp AppDomainSetup chứa các thông tin cấu hình cho một miền ứng dụng Bảng 3.1 kiệt kê các thuộc tính thường được sử dụng nhất của lớp AppDomainSetup khi tạo các miền ứng dụng Các thuộc tính này có thể được truy xuất sau khi tạo thông qua các thành viên của đối tượng
AppDomain, và một số có thể thay đổi lúc thực thi; bạn hãy tham khảo tài liệu .NET
Framework SDK về lớp AppDomain để hiểu chi tiết hơn
Bảng 3.1 Các thuộc tính thông dụng của lớp AppDomainSetup
ApplicationBase
Thư mục mà CRL sẽ xét trong quá trình dò tìm các assembly riêng Kỹ thuật dò tìm (probing) sẽ được thảo luận trong mục
3.5 Thực tế, ApplicationBase là thư mục gốc cho ứng dụng đang thực thi Theo mặc định, đây là thư mục chứa assembly
Có thể đọc được thuộc tính này sau khi tạo miền ứng dụng bằng thuộc tính AppDomain.BaseDirectory
Trang 9Tên của file cấu hình, được sử dụng bởi mã đã được nạp vào miền ứng dụng Có thể đọc được thuộc tính này sau khi tạo miền ứng dụng bằng phương thức AppDomain.GetData với khóa APP_CONFIG_FILE
DisallowPublisherPolicy
Quy định phần publisher policy của file cấu hình ứng dụng
có được xét đến hay không khi xác định phiên bản của một
assembly tên mạnh để nối kết Publisher policy sẽ được thảo
luận trong mục 3.5
PrivateBinPath
Danh sách các thư mục cách nhau bởi dấu chấm phẩy mà bộ thực thi sẽ sử dụng khi dò tìm các assembly riêng Các thư mục này có vị trí tương đối so với thư mục được chỉ định trong ApplicationBase Có thể đọc được thuộc tính này sau khi tạo miền ứng dụng bằng thuộc tính
AppDomain.RelativeSearchPath Có thể thay đổi thuộc tính này lúc thực thi bằng phương thức AppendPrivatePath và
ClearPrivatePath
Ví dụ dưới đây trình bày cách tạo và cấu hình một miền ứng dụng:
// Khởi tạo một đối tượng của lớp AppDomainSetup.
AppDomainSetup setupInfo = new AppDomainSetup();
// Cấu hình các thông tin cài đặt cho miền ứng dụng.
setupInfo.ApplicationBase = @"C:\MyRootDirectory";
setupInfo.ConfigurationFile = "MyApp.config";
setupInfo.PrivateBinPath = "bin;plugins;external";
// Tạo một miền ứng dụng mới (truyền null làm đối số chứng cứ).
// Nhớ lưu một tham chiếu đến AppDomain mới vì nó
// không thể được thu lấy theo bất kỳ cách nào khác.
AppDomain newDomain = AppDomain.CreateDomain(
"My New AppDomain",
new System.Security.Policy.Evidence(),
setupInfo);
Bạn phải duy trì một tham chiếu đến đối tượng AppDomain vừa tạo bởi vì không
có cơ chế nào để liệt kê các miền ứng dụng hiện có từ bên trong mã được-quản-lý.
Trang 102. Chuy n các đ i t Chuy n các đ i t ể ể ố ượ ố ượ ng qua l i các mi n ng d ng ng qua l i các mi n ng d ng ạ ạ ề ứ ề ứ ụ ụ
Bạn cần chuyển các đối tượng qua lại giữa các miền ứng dụng như các đối số hay
các giá trị trả về.
Sử dụng các đối tượng marshal-by-value hay marshal-by-reference.
Hệ thống NET Remoting (sẽ được thảo luận trong chương 12) giúp việc gởi các đối tượng qua lại các miền ứng dụng trở nên dễ dàng Tuy nhiên, nếu bạn chưa quen với NET Remoting, kết
quả có thể rất khác so với mong đợi Thực ra, vấn đề gây khó khăn khi dùng nhiều miền ứng
dụng là sự tương tác với NET Remoting và cách thức luân chuyển đối tượng qua các miền
ứng dụng
Tất cả các kiểu dữ liệu có thể chia thành ba loại: nonremotable, marshal-by-value (MBV), và
marshal-by-reference (MBR) Kiểu nonremotable không thể vượt qua biên miền ứng dụng và
không thể dùng làm các đối số hay các giá trị trả về của các lời gọi trong môi trường liên miền
ứng dụng Kiểu nonremotable sẽ được thảo luận trong mục 3.4.
Kiểu MBV là kiểu khả-tuần-tự-hóa Khi một đối tượng kiểu MBV được chuyển qua một miền ứng dụng khác như là đối số hay giá trị trả về, hệ thống NET Remoting sẽ tuần tự hóa trạng
thái hiện tại của đối tượng, chuyển dữ liệu đó sang miền ứng dụng đích, và tạo một bản sao của đối tượng với cùng trạng thái như đối tượng gốc Kết quả là tồn tại bản sao của đối tượng
ở cả hai miền ứng dụng Hai đối tượng này ban đầu giống nhau hoàn toàn, nhưng độc lập nhau, nên việc thay đổi đối tượng này không ảnh hưởng đến đối tượng kia Dưới đây là ví dụ một kiểu khả-tuần-tự-hóa có tên là Employee, được chuyển qua một miền ứng dụng khác bằng trị (xem mục 16.1 để biết cách tạo kiểu khả-tuần-tự-hóa)
[System.Serializable]
public class Employee {
// Hiện thực các thành viên ở đây.
§
}
Kiểu MBR là lớp dẫn xuất từ lớp System.MarshalByRefObject Khi một đối tượng kiểu MBR được chuyển qua một miền ứng dụng khác như đối số hay giá trị trả về, hệ thống NET
Remoting sẽ tạo một đối tượng proxy cho đối tượng MBV cần chuyển trong miền ứng dụng
đích Đối tượng đại diện thực hiện các hành vi hoàn toàn giống với đối tượng MBR mà nó đại diện Thực ra, khi thực hiện một hành vi trên đối tượng đại diện, hệ thống NET Remoting
thực hiện ngầm việc chuyển lời gọi và các đối số cần thiết đến miền ứng dụng nguồn, và tại
đó thực hiện lời gọi hàm trên đối tượng MBR gốc Kết quả được trả về thông qua đối tượng
đại diện Dưới đây là một phiên bản khác của lớp Employee, được chuyển qua một miền ứng dụng khác bằng tham chiếu thay vì bằng trị (xem mục 12.7 để biết chi tiết về cách tạo kiểu
MBR).
public class Employee : System.MarshalByRefObject {