Tải bản đầy đủ (.pdf) (10 trang)

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

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 (157.78 KB, 10 trang )

1.1
Thực thi assembly ở miền ứng dụng khác
V
V


Bạn cần thực thi một assembly ở một miền ứng dụng khác với miền ứng dụng
hiện hành.
#
#


Gọi phương thức ExecuteAssembly của đối tượng AppDomain đại diện cho
miền ứng dụng, và chỉ định tên của assembly cần thực thi.
Nếu bạn có một assembly khả-thực-thi và muốn nạp để thực thi nó trong một miền ứng
dụng, phương thức ExecuteAssembly sẽ giúp bạn. Phương thức ExecuteAssembly có bốn
dạng thức khác nhau. Dạng thức đơn giản nhất chỉ nhận vào một kiểu string chứa tên c
ủa
assembly cần thực thi; bạn có thể chỉ định một file cục bộ hay một URL. Một dạng thức
khác cho phép bạn chỉ định chứng cứ (evidence) cho assembly (xem mục 13.10) và các
đối số để truyền đến điểm nhập của assembly (tương đương với các đối số dòng lệnh).
Phương thức ExecuteAssembly nạp assembly được chỉ định và thực thi phương thức
được định nghĩa trong siêu d
ữ liệu là điểm nhập của assembly (thường là phương thức
Main). Nếu assembly được chỉ định không có khả năng thực thi, ExecuteAssembly sẽ
ném ngoại lệ System.Runtime.InteropServices.COMException. Bộ thực thi không thực
thi assembly trong một tiểu trình mới, vì thế quyền kiểm soát sẽ không trả về cho đến khi
quá trình thực thi của assembly kết thúc. Do ExecuteAssembly nạp một assembly bằng
tên riêng phần (chỉ có tên file), CLR sẽ không dùng GAC hay probing để tìm assembly
(xem mục 3.5 để bi
ết thêm chi tiết).


Ví dụ dưới đây trình bày cách sử dụng phương thức ExecuteAssembly để nạp và thực thi
một assembly. Lớp ExecuteAssemblyExample tạo một AppDomain và thực thi chính nó
trong AppDomain bằng phương thức ExecuteAssembly. Kết quả là có hai bản sao của
ExecuteAssemblyExample được nạp vào hai miền ứng dụng khác nhau.
using System;

public class ExecuteAssemblyExample {

public static void Main(string[] args) {

// Nếu assembly đang thực thi trong một AppDomain
// có tên thân thiện là "NewAppDomain"
// thì không tạo AppDomain mới. Điều này sẽ
// tránh một vòng lặp vô tận tạo AppDomain.
if (AppDomain.CurrentDomain.FriendlyName != "NewAppDomain") {

// Tạo miền ứng dụng mới có tên là "NewAppDomain".
AppDomain domain = AppDomain.CreateDomain("NewAppDomain");

// Thực thi assembly này trong AppDomain mới và
// truyền mảng các đối số dòng lệnh.
domain.ExecuteAssembly("ExecuteAssemblyExample.exe",
null, args);
}

// Hiển thị các đối số dòng lệnh lên màn hình
// cùng với tên thân thiện của AppDomain.
foreach (string s in args) {

Console.WriteLine(AppDomain.CurrentDomain.FriendlyName +

" : " + s);
}
}
}
1.2
Thể hiện hóa một kiểu trong miền ứng dụng khác
V
V


Bạn cần thể hiện hóa một kiểu trong một miền ứng dụng khác với miền ứng
dụng hiện hành.
#
#


Gọi phương thức CreateInstance hay CreateInstanceFrom của đối tượng
AppDomain đại diện cho miền ứng dụng đích.
Việc sử dụng phương thức ExecuteAssembly (đã được thảo luận trong mục 3.6) không
mấy khó khăn; nhưng khi phát triển các ứng dụng phức tạp có sử dụng nhiều miền ứng
dụng, chắc chắn bạn muốn kiểm soát quá trình nạp các assembly, tạo các kiểu dữ liệu, và
triệu g
ọi các thành viên của đối tượng bên trong miền ứng dụng.
Các phương thức CreateInstance và CreateInstanceFrom cung cấp nhiều phiên bản nạp
chồng giúp bạn kiểm soát quá trình tạo đối tượng. Các phiên bản đơn giản nhất sử dụng
phương thức khởi dựng mặc định của kiểu, nhưng cả hai phương thức này đều thiết đặt
các phiên bản cho phép bạn cung cấp đối số để sử dụng bấ
t kỳ phương thức khởi dựng
nào.
Phương thức CreateInstance nạp một assembly có tên xác định vào miền ứng dụng bằng

quá trình đã được mô tả cho phương thức Assembly.Load trong mục 3.5. Sau đó,
CreateInstance tạo đối tượng cho kiểu và trả về một tham chiếu đến đối tượng mới được
đóng gói trong ObjectHandle (được mô tả trong mục 3.3). Tương tự như thế đối với
phương thức CreateInstanceFrom; tuy nhiên, CreateInstanceFrom nạp assembly vào mi
ền
ứng dụng bằng quá trình đã được mô tả cho phương thức Assembly.LoadFrom trong mục
3.5.
Í
AppDomain cũng cung cấp hai phương thức rất tiện lợi có tên là
CreateInstanceAndUnwrap và CreateInstanceFromAndUnwrap, chúng sẽ tự
động khôi phục tham chiếu đến đối tượng đã được tạo từ đối tượng
ObjectHandle; bạn phải ép đối tượng trả về cho đúng kiểu trước khi sử dụng.
Nếu bạn sử dụng CreateInstance hay CreateInstanceFrom để tạo đối tượng kiểu MBV
trong một miền ứng dụng khác, đối tượ
ng sẽ được tạo nhưng tham chiếu trả về sẽ không
chỉ đến đối tượng đó. Do cách thức đối tượng MBV vượt qua biên miền ứng dụng, tham
chiếu này sẽ chỉ đến một bản sao của đối tượng được tạo tự động trong miền ứng dụng
cục bộ. Chỉ khi bạn tạo một kiểu MBR thì tham chiếu trả về mớ
i chỉ đến đối tượng trong
miền ứng dụng khác (xem mục 3.2 để biết thêm chi tiết về kiểu MBV và MBR).
Kỹ thuật chung để đơn giản hóa việc quản lý các miền ứng dụng là sử dụng lớp điều
khiển (controller class). Một lớp điều khiển là một kiểu MBR tùy biến. Bạn hãy tạo một
miền ứng dụng rồi t
ạo đối tượng lớp điều khiển trong miền ứng dụng này bằng phương
thức CreateInstance. Lớp điều khiển hiện thực các chức năng cần thiết cho ứng dụng để
thao tác miền ứng dụng và các nội dung của nó. Các chức năng này có thể bao gồm: nạp
assembly, tạo thêm miền ứng dụng, dọn dẹp trước khi xóa miền ứng dụng, hay liệt kê các
phần tử
chương trình (bạn không thể thực hiện ở bên ngoài miền ứng dụng).
Ví dụ dưới đây trình bày cách sử dụng một lớp điều khiển có tên là PluginManager. Khi

đã được tạo trong một miền ứng dụng, PluginManager cho phép bạn tạo đối tượng của
các lớp có hiện thực giao diện IPlugin, chạy và dừng các plug-in đó, và trả về danh sách
các plug-in hiện được nạp.
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Specialized;

// Giao diện chung cho tất cả các plug-in.
public interface IPlugin {
void Start();
void Stop();
}

// Một hiện thực đơn giản cho giao diện Iplugin
// để minh họa lớp điều khiển PluginManager.
public class SimplePlugin : IPlugin {

public void Start() {
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName +
": SimplePlugin starting...");
}

public void Stop() {
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName +
": SimplePlugin stopping...");
}
}

// Lớp điều khiển, quản lý việc nạp và thao tác

// các plug-in trong miền ứng dụng của nó.
public class PluginManager : MarshalByRefObject {

// ListDictionary giữ tham chiếu đến các plug-in.
private ListDictionary plugins = new ListDictionary();

// Phương thức khởi dựng mặc định.
public PluginManager() {}

// Phương thức khởi dựng nhận danh sách các plug-in.
public PluginManager(ListDictionary pluginList) {

// Nạp các plug-in đã được chỉ định.
foreach (string plugin in pluginList.Keys) {

this.LoadPlugin((string)pluginList[plugin], plugin);
}
}

// Nạp assembly và tạo plug-in được chỉ định.
public bool LoadPlugin(string assemblyName, string pluginName) {

try {

// Nạp assembly.
Assembly assembly = Assembly.Load(assemblyName);

// Tạo plug-in mới.
IPlugin plugin =
(IPlugin)assembly.CreateInstance(pluginName, true);


if (plugin != null) {

×