Lập trình với C#: Chương 1 (Phần III)

Assemblies

Một assembly là một đơn vị luận lí chứa mã đã được biên dịch sang .NET. Chúng ta sẽ bàn kĩ về các assemblie trong chương 8, ở đây chúng ta sẽ nói sơ về nó.

Một assembly là một tự mô tả đầy đủ, và nó giống một đơn vị luận lí hơn là một đơn vị vật lí, điều đó có nghĩa là nó có thể chứa trong nhiều file (thật vậy các assemblie động được lưu trong bộ nhớ không phải trong file). Nếu một assembly được lưu trong nhiều file, thì sẽ có một file chính chứa các con trỏ và các mô tả về các file khác của assembly.

Chú ý rằng, câu trúc assembly được dùng chung cho cả mã thi hành và mã thư viện. Sự khác biệt duy nhất là assembly thi hành chứa lối vào chương trình chính trong khi assembly thư viện thì không có.

Một điểm quan trọng trong các assembly là chúng chứa metadata dùng để mô tả các kiểu và phương thức được định nghĩa trong mã tương ứng. Một assembly, tất nhiên cũng chứ assembly metadata dùng để mô tả chính assembly đó. Assembly metadata này, chứa một vùng đựơc hiểu như là manifest, cho phép kiểm tra phiên bản và tình trạng của assembly.

ildasm, một tiện ích có sẵn của Windows, có thể dùng để nghiên cứu nội dung của một assembly, bao gồm manifest metadata. Chúng ta sẽ lấy vi dụ về ildasm trong chương 8.

Thật vậy một assembly chứa metadata của chương trình nghĩa là các ứng dụng hoặc các assembly khác có thể gọi mã trong môt assembly mà không cần tham chiếu đến Registry, hoặc một dữ liệu nguồn khác,. Một điểm quan trọng trong cách làm của COM cũ, các GUID của các thành phần và giao diện interfaces không thể đạt được từ Registry.

Việc dàn trải dự liệu thành 3 định vị khác nhau đồng nghĩa với việc tạo ra mối nguy hiểm trong đồng bộ hoá, nó ngăn không cho các thành phần khác sử dụng. Với assemblies, sẽ không còn những mối nguy hiểm như vậy, bởi vì tất các các metadata được lưu trong bộ lệnh thi hành của chương trình. Chú ý rằng dù cho các assemblie được lưu thành một vài file, chúng vẫn không gây vấn đề gì về đồng bộ hoá dữ liệu. Đó là vì nhờ vào file assembly chính, file này chứa đường dẫn, các thông tin chi tiết, mã băm, và nội dung của các file khác, điều đó có nghĩa là nếu một file bị thay thế, hay bị phá hoại, nó sẽ được tìm ra và sẽ không cho load.

Assemblies bao gồm 2 loại: các sharedprivate assembly.

Private Assemblies

Private assemblies là kiểu đơn giản nhất. Nó chứa phần mềm và chỉ được dùng cho phần mềm đó. Với phần mô tả này bạn có thể chứa đựng các private assemblie hòng cung cấp cho một ứng dụng kiểu thực thi và một số thư viện, các thư viện này chứa mã sẽ được thi hành bởi ứng dụng đó.

Hệ thống đảm bảo rằng private assemblies sẽ không được dùng bởi phần mềm khác, bởi vì một ứng dụng chỉ có thể load private assemblies trong cùng folder với chương trình chính hoặc là trong một thư mục con của nó.

Chúng ta không thể tin cậy rằng tất cả các phần mềm luôn được cài đặt trong thư mục của nó, nghĩa là sẽ không bao giờ có chuyện một gói phần mềm ghi đè, sửa chữa hoặc vô tình load một private assemblies dành riền cho một gói khác. Vậy làm sao để các Private assemblie chỉ được dùng bởi gói phần mềm mà nó mô tả? Cần có một cơ chế bảo vệ, sao cho khi một sản phẩm thương mại khác cài đè lên một phiên bản assembly mới (chưa kể đến các chương trình đựơc thiết kế để phá hoại), thì sẽ không có chuyện tranh chấp tên. Nếu có sự trùng tên trong các assembly, đều đó không quan trọng và các ứng dụng chỉ có thể nhìn thấy một bộ các assembly.

Bởi vì một private assembly  là một tự định nghĩa trọn vẹn, tiến trình xử lí cực kì đơn giản. Bạn đơn giản thay thế các file thích hợp vào thư mục thíhc hợp trong file hệ thống (Không cần phải đăng kí trong registry). Tiến trình này được gọi là zero impact (xcopy) installation.

Shared Assemblies

Shared assemblies được dành cho cácc thư viện công cộng có thể dùng cho bất kì ứng dụng nào. Bởi vì bất kì ứng dụng nào cũng có thể truy xuất một shared assembly, cần phải có các cơ chế để bảo vệ các rủi ro sau:

  • Tranh chấp tên, khi một công ty tạo ra các shared assembly trùng tên với các shared assembly sẵn có của bạn. Về mặt lí thuyết mã của bạn có thể truy xuất vào cả hai assembly này song đây có thể là một vấn đề phức tạp.

  • Lỗi của một assembly có thể bị ghi đè bởi một phiên bản khác của cùng same assembly – một phiên bản mới không tương thích với những gì sẵn có.

Giải pháp cho những vấn đề trên là đặt các shared assembly trong một cây thư mục đặt biệt của hệ thống,  có thể xem như là assembly cache toàn cục. Không giống như các private assembly, nó không đơn giản là copy assembly sang một thư mục thích hợp – nó cần được cài đặt rõ ràng vào cache. Tiến trình này có thể được thực thi bởi một số tiện ích của .NET, bao gồm luôn quá trình kiểm tra trên assembly, tương tự như cài đặt một thư mục trong assembly cache để đảm bảo tính toàn vẹn của assembly.

Để tránh tranh chấp tên, shared assemblies đưa ra một được quản lí dựa trên một khóa mật mã chính. Tên này được gọi là strong name, được bảo đảm về tính độc nhất, và phải được trích dẫn bởi ứng dụng muốn tham chiếu đến một shared assembly.

Vấn đề về tương thích với lỗi do ghi đè một assembly được đánh địa chỉ theo thông tín phiên bản trong assembly manifest, và cho phép cài đặt song song.

Reflection

Từ khi các assembly được lưu dưới dạng metadata, bao gồm chi tiết về tất cả các kiểu và thành viên của những kiểu này, thì nó có thể được truy xuất được các metadata programmatically. Để biết chi tiết hơn, xin hãy xem reflection – mã quả có thể xem xét các mã quản khác, hoặc xem xét chính nó, để nhận ra các thông tin về mã. Bạn có thể dùng các attribute, để có thể sử dụng phương thức trong lúc chạy điều này tốt hơn là trong lúc biên dịch.