Tạo các Assembly chia sẽ Assemblies có thể được tách biệt cho người sử dụng bởi một ứng dụng độc lập – không chia sẽ một assembly là mặc định. Khi sử dụng assemblies nó không cần thiết lưu ý các yêu cầu dành cho chia sẽ. Nội dung chính chúng ta sẽ được khảo sát: • Strong names • Tạo shared assemblies • Cài đặt shared assemblies trong global assembly cache • Sử dụng một assembly chia sẽ Tên Assembly chia sẽ Mục đích của tên assembly chia sẽ phải là duy nhất, và nó phải có khả năng để bảo vệ tên. Tránh 1 lúc nào đó có người lạ tạo một assembly sử dụng cùng tên. Bạn có thể tạo ra những assembly được chia sẻ sử dụng bởi những ứng dụng khác. Nếu bạn viết ra một ô control mang tính chung chung (general control) hoặc một lớp có thể được chia sẻ sử d ụng bởi nhiều nhà triển khai khác, đó là bạn đang thực hiện một shared assembly. Trước tiên, assembly của bạn phải có một strong name, một tên duy nhất được chia sẻ sử dụng. Thứ đến, shared assembly của bạn phải được bảo vệ không cho các phiên bản mới phá bĩnh, như vậy phải có cách kiểm tra phiên bản trước khi được nạp vào theo yêu cầu của ứng dụng client. Cuối cùng, muốn cho chia sẻ sử dụ ng assembly bạn tạo ra, bạn phải đưa assembly bày vào Global Assembly Cache (GAC). Đây là một vùng ký ức của hệ thống các tập tin được dành riêng bởi CLR để trữ các shared assembly. Bản thân GAC nằm ở thư mục <ổ đia>:\WINNT\Assembly. Trên .NET, các shared assembly đều được tập trung đưa vào một nơi là GAC. Khái niệm về Strong Name Để có thể sử dụng shared assembly, bạn cần tuân thủ 3 đòi hỏi sau đay: • Bạn phải có khả năng báo đúng assembly mà bạn muốn nạp vào. Do đó, bạn cần có một tên duy nhất mang tính toàn cục (global unique name) được gán cho shared asembly. • Bạn cần bảo đảm là assembly không bị giả mạo. Nghĩa là, bạn cần có một digital signature (dấu ấn kỹ thuật số) khi assembly được tạo dựng. • Bạn cần bảo đảm là assembly bạn đang nạp vào đúng là assembly được phép của tác giả tạo ra assembly. Do đó, bạn cần ghi nhận mã nhận diện người sáng tác (originator). Do đó, khi bạn muốn tạo ra một assembly có thể được chia sẻ sử dụng bởi nhiều ứng dụng khác nhau trên một máy tính nào đó, bước đầu tên là tạo ra một tên chia sẻ duy nhất đối với assembly, Tên này được gọi là strong name thường chứa nhữ ng thông tin sau đây: • Một tên kiểu string mang tính thân thiện và thông tin tuỳ chọn về culture (giống như với private assembly) • Một mã nhận diện phiên bản • Một cặp mục khoá public-private • Một dấu ấn kỹ thuật số (digital signature). Việc hình thành một strong name đều được dựa trên một phương thức mật mã hoá chuẩn mục khoá công cộng (standard public key encryption). Khi bạn tạo một shared assembly bạn phải kết sinh một cặp mục khoá public-private. Một đoạn mã băm (hash code) được lấy ra từ những tên và nội dung của các tập tin trong assembly. Mã băm này sẽ được mật mã hoá với một private key đối với assembly và được đư a vào manifest. Đây được biết là ký tên assembly (signing the assembly). Public key sẽ được sát nhập vào strong name của assembly. Nói tóm lại, một cặp mục khoá sẽ được bao gồm trong chu kỳ build sử dụng mọt trình biên dịch .NET, trình này sẽ liệt kê một token của public key trên manifest của assembly (thông qua tag [.publickeytoken]). Private key sẽ không được liệt kê ra trên manifest nhưng lại được "ký tên" với public key. Dấu ấn kết quả sẽ được trữ tập tin định nghĩa assembly manifest). Khi một ứng dụng cho nạp assembly vào, thì CLR sẽ dùng public key để giải mã đoạn mã băm đối với các tập tin thuộc assembly bảo đảm là chúng không bị giả mạo. Việc này cũng bảo vệ chống đụng độ về tên. Tạo một shared assembly Muốn kết sinh một strong name bạn sử dụng trình tiện ích sn.exe. (nằm trên thư mục C:\program Files\Microsoft.NET\SDK\v1.1\bin). Mặc dù trình tiện ích này có nhiều mục chọn, ta chỉ cần dùng flag "-k" yêu cầu trình tiện ích kết sinh một strong name mớ i và được trữ trên một tập tin được khai báo. vi du: sn -k d:\vidu_C#\chuong8\example.snk Bạn có thể đặt tên tập tin bất cứ tên gì bạn muốn. Bạn nhớ cho strong name là một chuỗi kexadecimal digit và không dành cho người đọc. Nếu bạn quan sát nội dung của tập tin mới này (example.snk), bạn thấy binary markings của cặp key. Bước kế tiếp là cho ghi nhận public key lên assembly manifest. Cách dễ nhất là sử dụng attribute AssemblyKeyfile. Khi bạn tạo một C# project workspace, có thể bạn để ý một trong những tập tin khởi sự của dự án mang tên "AssemblyInfo.cs", Tậ p tin này chứa một số attributes được tiêu thụ bởi một trình biên dịch . NET. Nếu bạn quan sát tập tin này, bạn sẽ thấy attribute AssemblyKeyFile này. Muốn khai báo một strong name đối với một shared assembly, bạn chỉ cần nhập từ trị của attribute này cho biết nơi tá túc của tập tin *.snk. [asssembly:AssemblyKeyFile(@"D:\vidu_C#\chuong8\example.snk:)] Sử dụng assembly level attribute này, C# compiler giờ đây trộn với nhau thông tin cần thiết vào manifest tương ứng. Bạn có thể dùng ILDasm.exe để xem tag [.publickey]. Ví dụ: ta có file mykey.snk sn -k mykey.snk Ở đây ta thay thành AssemblyInfo.cs. Thuộc tính AssemblyKeyFile được thiết lập đến file mykey.snk: [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile(" / /mykey.snk")] [assembly: AssemblyKeyName("")] Sau khi xây dựng lại , Khoá công cộng có thể tìm thấy trong manifest khi nhìn vào assembly sử dụng ildasm: Trong ví dụ này chúng tôi sẽ tạo một shared assembly và một client để sử dụng nó.Đầu tiên ta bắt đầu với Visual C# Class Library project. Tôi thay đổi namespace thành Wrox.ProCSharp.Assemblies.Sharing, và tên lớp thành SimpleShared. Lớp này sẽ đọc tất cả hàng của file đã truyền bên trong constructor trong một StringCollection tại thời gian tạo thành, và trả về một chuỗi ngẫu nhiên trong phương thức GetQuoteOfTheDay() using System; using System.Collections.Specialized; using System.IO; namespace Wrox.ProCSharp.Assemblies.Sharing { public class SimpleShared { private StringCollection quotes; private Random random; public SimpleShared(string filename) { quotes = new StringCollection(); Stream stream = File.OpenRead(filename); StreamReader streamReader = new StreamReader(stream); string quote; while ((quote = streamReader.ReadLine()) != null) { quotes.Add(quote); } streamReader.Close(); stream.Close(); random = new Random(); } public string GetQuoteOfTheDay() { int index = random.Next(1, quotes.Count); return quotes[index]; } } } Tên chương trình bạn tham khảo kèm theo SimpleShared Cài đặt assembly vào GAC Một khi bạn đã thiết lập một strong name đối với một shared assembly, bước cuối cùng là cho cài đặt nó vào GAC, một thư mục hệ thống được dành riêng. Cách đơn giản nhất để cài đặt một shared assembly vào GAC là cho mở Window Explorer rồi lôi thả tập tin SharedAssembly.dll vào thư mục GAC hiên dịch (active window). Muốn thấy GAC, bạn cho mở Windows Explorer rồi hướng về\WINNT\Assembly sẽ nhảy qua một trình tiện ích GAC. Hoặc bạn cũng có thể tự do dùng trình tiện ích gacutil.exe như tiện ích trên command line như sau: gacutil /i: SharedAssembly.dll Theo ví dụ trên thì bạn nhập vào gacutil /i SimpleShared.dll Bạn nên nhớ là bạn phải có quyền Administrative đối với máy tính để có thể cài đặt assembly lên GAC. Đi ều này tốt thôi, vì nó ngăn ngừa người sử dụng nào đó phá bĩnh một cách vô tình những ứng dụng hiện hữu Kết quả cuối cùng là assembly của bạn giời đây nằm trong GAC và có thể được chia sẻ sử dụng bởi nhiều ứng dụng trên máy tính đích. Bạn để ý, khi nào bạn muốn gỡ bỏ một assembly khỏi GAC, bạn chỉ cần right-click lên assembly, rồi chon lick mục Delete trên trình đơn shortcut. Sử dụng một Shared Assembly Bây giờ để chứng minh, giả sử bạn tạo một ứng dụng C# Console Appication mới, cho mang tên SharedAssembly User chẳng hạn, cho qui chiếu về SharedAssembly binary, và bạn định nghĩa lớp sau đây Bạn nhớ cho, là khi một qui chiếu về một private assembly, IDE tự động tạo một bản sao của private assembly nàydành cho ứng dụng client dùng. Tuy nhiên, khi bạn qui chiếu một assembly có chứa một public key (như trong trường hợp sharedAssembly.dll) bạn sẽ không nhận một bản sao local. Giả định là những assembly nào có chứa public key là dùng chia sẻ sử dụng (và như thế phải nằm trong GAC). Bạn nhớ cho là Visual Studio .NET IDE cho phép bạn điều khiển một cách tường minh việc sao chép một assembly vào đó sử dụng cửa sổ properties. Thí dụ, nếu bạn cho đặt để một qui chiếu về một external binary, bạn chọn assembly vày sử dụng đến axternal binary, bạn chọn assembly này sử dụ ng đến Solution Explorer cho hiện lên cửa sổ Properties, rồi cho đặt để thuộc tính Copy Local về false. Việc lamf này sẽ gỡ bỏ local copy. Bây giờ, bạn cho chạy ứng dụng client lại nữa. Nó sẽ chạy tốt vì .NET Runtime sẽ tham khảo GAC để giải quyết việc dò tìm nơi tá túc của assembly được qui chiếu. Nếu bạn cho gỡ bỏ SharedAssembly.dll trên GAC, rồi cho chạy lại chương trình thì một biệt lệ System.IO.FileNotfound sẽ được tung ra. Trở lại ví dụ ban đầu để sử dụng Shared Assembly Để dùng shared assembly chúng ta sẽ tạo một C# Console Application gọi Client. Thay cho việc thêm project mới cho solution trước đây, bạn nên tạo một solution để shared assembly không nhận xây dựng lại khi xây dựng lại client. Tôi thay tên của namespace thành Wrox.ProCSharp.Assemblies.Sharing, và tên lớp thành Client. Chúng ta tham khảo assembly SimpleShared giống như cách chúng ta tham khảo private assemblies: dùng menu Project | Add Reference, hoặc Solution Explorer. sau đó ch ọn nút Browse để tìm assembly SimpleShared. Sau đây là đoạn mã của ứng dụng client using System; namespace Wrox.ProCSharp.Assemblies.Sharing { class Client { [STAThread] static void Main(string[] args) { SimpleShared quotes = new SimpleShared( @"C:\ProCSharp\Assemblies\Quotes.txt"); for (int i=0; i < 3; i++) { Console.WriteLine(quotes.GetQuoteOfTheDay()); Console.WriteLine(); } } } } Download chương trình Client Khi hiển thị manifest trong client assembly dùng ildasm chúng ta có thể tham khảo vào shared assembly SimpleShared: .assembly mở rộng SimpleShared. Phần thông tin tham khảo là số phiên bản chúng ta sẽ học ở phần tới và mã thông báo của khoá công cộng. Chúng ta dùng tiện ích sn –T hiển thị mã thông báo của khoá công cộng trong assembly. Kết quả của chương tình được hiển thị như sau: . ta thay thành AssemblyInfo.cs. Thuộc tính AssemblyKeyFile được thiết lập đến file mykey.snk: [assembly: AssemblyDelaySign(false)] [assembly: AssemblyKeyFile(" / /mykey.snk")]. đối với assembly và được đư a vào manifest. Đây được biết là ký tên assembly (signing the assembly) . Public key sẽ được sát nhập vào strong name của assembly.