Tài liệu C# và Các Lớp Đối Tượng part 5 docx

7 324 0
Tài liệu C# và Các Lớp Đối Tượng part 5 docx

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

Thông tin tài liệu

Attribute tuỳ chọn Trong chương 4 ta đã xem xét một số attribute được định nghĩa trên một số mục của chương trình.Đó là các attribute mà trình biên dịch biết cách xử lý .trong phần này ta sẽ xét việc định nghĩa các attribute của riêng ta .nếu ta làm điều này có thể các attribute này sẽ không được thừa nhận như là dữ liệu thêm (metadata) để trình biên dịch có thể xử lí. nhưng các metadata này có thể hữu ích cho mục đích tài liệu hướng dẫn .tuy nhiên, b ằng cách dùng các lớp trong namespace System.Reflection, mã của ta có thể đọc được các metadata vào lúc chạy.nghĩa là các attribute tùy chọn mà ta định nghĩa có thể ảnh hưởng trực tiếp đến cách mà mã chạy. Viết attribute tuỳ chọn Để hiểu cách viết attribute tuỳ chọn, ta cần xem trình biên dịch làm gì khi nó gặp 1 mục trong mã được đánh dấu với 1 attribute, mà việc hổ trợ không tường minh không được xây dựng trong trình biên dịch.giả sử ta có thuộc tính khai báo như sau: [FieldName("SocialSecurityNumber")] public string SocialSecurityNumber { get { // vv Như ta thấy thuộc tính này có 1 attribute ,Fieldname, trình biên dịch sẽ nối chuổi attribute với tên này thành FieldNameattribute, sau đó tìm trong tất cả các namespace ( đưọc đề cập trong using ) lớp có tên này.tuy nhiên nếu ta đánh dấu 1 mục với 1 attribute mà tên của nó có phần cuối là attribute thì trình biên dịch sẽ không thêm chuỗi attribute lần nữa ví dụ: [FieldNameattribute("SocialSecurityNumber")] public string SocialSecurityNumber { // vv Nếu trình biên dịch không tìm thấy 1 lớp attribute đáp ứng, hoặc thấy nhưng cách mà ta dùng attribute không phù hợp với thông tin trong lớp attribute.thì trình biên dịch sẽ sinh ra lỗi. Các lớp attribute tuỳ chọn Giả sử như ta đã định nghĩa 1 attribute FieldName như sau : [AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=false)] public class FieldNameAttribute : Attribute { private string name; public FieldNameAttribute(string name) { this.name = name; } } Attribute attributeUsage Điều đầu tiên ta chú ý là lớp attribute được đánh dấu với 1 attribute - attributeUsage . attributeUsage chỉ định các mục nào trong mã của ta attribute tuỳ chọn được áp dụng. thông tin này được cho bởi thông số đầu tiên, mà phải được trình bày. thông số này là 1 kiểu liệt kê,attributeTargets .trong ví dụ trên ta chỉ định attribute Fieldname có thể chỉ ứng dụng đến các thuộc tính. định nghĩa của kiểu liệt kê attributeTargets là : public enum attributeTargets { All = 0x00003FFF, Assembly = 0x00000001, Class = 0x00000004, Constructor = 0x00000020, Delegate = 0x00001000, Enum = 0x00000010, Event = 0x00000200, Field = 0x00000100, Interface = 0x00000400, Method = 0x00000040, Module = 0x00000002, Parameter = 0x00000800, Property = 0x00000080, ReturnValue = 0x00002000, Struct = 0x00000008 } Danh sách cho ta tất cả các attribute có thể đưọc áp dụng.khi áp dụng attribute đến các phần tử chương trình , ta đặt attribute trong ngoặc vuông ngay trước phần tử. tuy nhiên có 1 giá trị trong dánh sách trên không phù hợp đến bất kì phần tử nào trong chương trình :Assembly . 1 attribute có thể được áp dụng đến 1 Assembly như là thay thế hoàn toàn 1 phần tử trong mã. trong trường hợp này attribute có thể được đặt ở bất cứ đâu trong mã nguồn, nhưng cần được đánh dấu với từ khoá Assembly: [assembly: SomeAssemblyattribute(Parameters)] Ta có thể kết hợp nhiều kiểu áp dụng trên các phần tử ta dùng các tác tử, ví dụ như ta chỉ định attribute Fielaname có thể áp dụng đến 1 property hay 1 field ta viết như sau : [attributeUsage(attributeTargets.Property | attributeTargets.Field, AllowMultiple=false, Inherited=false)] public class FieldNameattribute : attribute Ta cũng có thể dùng attributeTargets.All để áp dụng attribute ở mọi nơi. attribute attributeUsage còn chứa 2 thông số khác là AllowMultiple and Inherited. chỉ định với cú pháp khác của <attributeName>=<attributeValue>, .thông số này là tuỳ chọn. thông số AllowMultiple chỉ định 1 attribute có thể áp dụng nhiều hơn 1 lần đến cùng 1 mục.nếu thiết đặt là false thì trình biên dịch sẽ thông báo lỗi nếu nó thấy :[FieldName("SocialSecurityNumber")] [FieldName("NationalInsuranceNumber")] public string SocialSecurityNumber { // vv Nếu thông số Inherited là true, thì 1 attribute có thể áp dụng đến 1 lớp hay 1 interface cũng sẽ được áp dụng đến tất cả các lớp hay interface được thừa kế.nếu attribute được áp dụng đến phương thức hay thuộc tính thì nó tự động áp dụng đến bất kì override của phương thức hay thuộc tính đó. Đặc tả các thông số attribute Ta sẽ kiểm tra làm thế nào ta có thể chỉ định bất kì thông số mà attribute tuỳ chọn nhận.cách nó làm việc khi trình biên dịch gặp 1 lệnh như : [FieldName("SocialSecurityNumber")] public string SocialSecurityNumber { // etc. Nó kiểm tra thông số truyền vào attribute - trong trường hợp này là chuỗi và tìm hàm dựng của attribute mà nhận các thông số này.nếu thấy thì không có vấn đề gì ngược lại trình biên dịch sẽ sinh ra lỗi. Các thông số tuỳ chọn Ta thấy attribute attributeUsage có 1 cú pháp thay thế mà các thông số tuỳ chọn có thể được thêm vào thành 1 attribute.cú pháp này có liên quan đến việc chỉ định tên của các thông số tùy chọn.giả sử ta cập nhật lại thuộc tính SocialSecurityNumber như sau : [FieldName("SocialSecurityNumber", Comment="This is the primary key field")] public string SocialSecurityNumber { // etc. Trong trường hợp này , trình biên dịch sẽ nhận ra<ParameterName>= cú pháp của thông số thứ hai.nó sẽ tìm 1 thuộc tính public ( hoặc field) của tên đó mà nó có thể dùng để đặt giá trị của thông số này. nếu ta muốn đoạn mã trên làm việc ta thêm mã sau vào FieldNameattribute: [attributeUsage(attributeTargets.Property, AllowMultiple=false, Inherited=false)] public class FieldNameattribute : attribute { private string comment; public string Comment { // etc. Ví dụ WhatsNewattributes Ví dụ cung cấp 1 attribute chỉ định khi nào 1 mục được cập nhật lần cuối.trong đó nó bao gồm 3 assembly riêng biệt : assembly WhatsNewattributes chứa đựng định nghĩa của các attribute assembly VectorStruct ,chứa đựng mã mà attribute được áp dụng. assembly LookUpWhatsNew chứa đựng dự án trình bày chi tiết các mục mà vừa thay đổi. Thư viện assembly WhatsNewattributes Mã nguồn chứa trong tập tin WhatsNewattributes.cs.để biên dịch ta gõ : csc /target:library WhatsNewattributes.cs Mã nguồn của assembly này chứa 2 lớp attribute . LastModifiedattribute and SupportsWhatsNewattribute. LastModifiedattribute là attribute mà ta có thể dùng để đánh d ấu khi một mục được cập nhật lần cuối . nó nhận 2 thông số bắt buộc ( các thông số mà đưọc truyền đến hàm dựng) ngày tháng cập nhật , và chuỗi chứa mô tả các thay đổi. cũng có 1 thông số tuỳ chọn missuses, được dùng để mô tả bất kì vấn đề nào phát sinh trong mục. Mã nguồn cho phần này như sau : namespace Wrox.ProCSharp.WhatsNewAttributes { [AttributeUsage( AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true, Inherited=false)] public class LastModifiedAttribute : Attribute { private DateTime dateModified; private string changes; private string issues; public LastModifiedAttribute(string dateModified, string changes) { this.dateModified = DateTime.Parse(dateModified); this.changes = changes; } public DateTime DateModified { get { return dateModified; } } public string Changes { get { return changes; } } public string Issues { get { return issues; } set { issues = value; } } } [AttributeUsage(AttributeTargets.Assembly)] public class SupportsWhatsNewAttribute : Attribute { } } Dùng các attribute này - assembly VectorClass Tiếp theo ta cần dùng các attribute này trong ví dụ VectorAsCollection . ta cần tham chiếu tuờng minh thư viện WhatsNewattributes mà ta vừa mới tạo. ta cũng cần chỉ định namespace để trình biên dịch nhận ra attribute : using System; using Wrox.ProCSharp.WhatsNewattributes; using System.Collections; using System.Text; [assembly: SupportsWhatsNew] Ta thêm vào dòng mà sẽ đánh dấu assembly với attribute SupportsWhatsNew Trong phần mã của lớp Vector . ta không thật sự thay đổi bất cứ thứ gì trong lớp này , chỉ thêm vào vài attribute LastModified. tuy nhiên ta cũng tạo ra 1 thay đổi , ta vừa định nghĩa Vector như là 1 lớp thay vì là 1 struct. lý do là mã mà ta sẽ viết sau trình bày các attribute .trong ví dụ VectorAsCollection ,Vector là 1 struct nhưng bảng kiệt kê của nó là 1 lớp .có cả hai kiểu là lớp nghĩa là ta không phải lo lắng về sự tồn tại của bất kì struct , do đó làm cho ví dụ của ta ngắn hơn 1 chút . namespace Wrox.ProCSharp.VectorClass { [LastModified("14 Feb 2002", "IEnumerable interface implemented\n" + "So Vector can now be treated as a collection")] [LastModified("10 Feb 2002", "IFormattable interface implemented\n" + "So Vector now responds to format specifiers N and VE")] class Vector : IFormattable, IEnumerable { public double x, y, z; public Vector(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } [LastModified("10 Feb 2002", "Method added in order to provide formatting support")] public string ToString(string format, IFormatProvider formatProvider) { if (format == null) return ToString(); Ta cũng sẽ đánh dấu lớp VectorEnumerator chứa như new: [LastModified("14 Feb 2002", "Class created as part of collection support for Vector")] private class VectorEnumerator : IEnumerator { Tuy nhiên ta vẫn chưa thể chạy bởi vì ta chỉ mới có 2 thư viện .ta sẽ phát triển phần cuối của ví dụ mà sẽ tìm và trình bày các attribute sau khi học xong Reflection. Để biên dịch đoạn mã này ta gõ : csc /target:library /reference:WhatsNewattributes.dll VectorClass.cs Code for Download: WhatsNewattributes.cs VectorClass.cs  . thừa nhận như là dữ liệu thêm (metadata) để trình biên dịch có thể xử lí. nhưng các metadata này có thể hữu ích cho mục đích tài liệu hướng dẫn .tuy nhiên,. chứa như new: [LastModified("14 Feb 2002", "Class created as part of collection support for Vector")] private class VectorEnumerator

Ngày đăng: 26/01/2014, 14:20

Từ khóa liên quan

Tài liệu cùng người dùng

Tài liệu liên quan