intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

C# và Các Lớp Đối Tượng part 6

Chia sẻ: Dqdsadasd Qwdasdsad | Ngày: | Loại File: PDF | Số trang:10

77
lượt xem
8
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Reflection Reflection là 1 thuật ngữ bao phủ 1 lớp cơ sở khác của .NET mà cho phép ta tìm ra thông tin về các kiểu trong chương trình. hầu hết những lớp này nằm trong namespace System.Reflection, và có 1 số lớn các lớp khác trong namespace này. trong phần này ta sẽ tìm hiểu lớp system.

Chủ đề:
Lưu

Nội dung Text: C# và Các Lớp Đối Tượng part 6

  1. Reflection Reflection là 1 thuật ngữ bao phủ 1 lớp cơ sở khác của .NET mà cho phép ta tìm ra thông tin về các kiểu trong chương trình. hầu hết những lớp này nằm trong namespace System.Reflection, và có 1 số lớn các lớp khác trong namespace này. trong phần này ta sẽ tìm hiểu lớp system.Type , mà cho phép ta truy nhập thông tin liên quan đến việc định nghĩa bất kì kiểu dữ liệu nào được cho.tiếp theo ta sẽ tìm hiểu lớp System.Reflection.assembly mà cho phép ta truy xuất thông tin về assembly được cho, hoặc tải assembly đó vào trong chương trình của ta.cuối cùng ta sẽ xét ví dụ WhatsNewAttributes Lớp System.Type Ta đã dùng lớp Type 1 số lần để lấy tên của 1 kiểu : Type t = typeof(double) Mặc dù ta cho rằng type là 1 lớp nhưng thực sự nó là 1 lớp cơ sở trừu tượng, bất cứ khi nào ta khởi tạo 1 đối tượng type ta thực sự khởi tạo 1 lớp dẫn xuất của type.type có 1 lớp dẫn xuất đáp ứng mỗi kiểu dữ liệu.có 3 cách lấy 1 tham chiếu Type mà chuyển cho kiểu dữ liệu bất kì: - Dùng tác tử typeof. tác tử này lấy tên của kiểu như là thông số . - Dùng phương thức Gettype() , mà tất cả các lớp kế thừa từ System.Object: double d = 10;Type t = d.GetType(); Gettype() hữu ích khi ta có 1 tham chiếu đối tượng và không chắc đối tượng thực sự là thể hiện của lớp nào - Ta cũng có thể gọi phương thức static của lớp type ,getType(): Type t = Type.GetType("System.Double"); Các thuộc tính của Type 1. 1 số thuộc tính lấy chuỗi chứa các tên khác nhau kết hợp với lớp : Thuộc tính Trả về Name tên của kiểu dữ liệu FullName tên đầy đủ bao gồm cả namespace Namespace tên namespace của kiểu dữ liệu. 2. Có thể lấy những tham chiếu đến kiểu những đối tượng mà trình bày các lớp có liên quan : Thuộc tính Kiểu tham chiếu trả về tương ứng với BaseType kiểu cơ sở trực tiếp của kiểu này UnderlyingSystemType kiểu mà kiểu này ánh xạ trong thời gian chạy .NET
  2. 3. 1 số thuộc tính luận lý chỉ định liệu có phải là kiểu nào đó hay không ví dụ là 1 lớp hay 1 kiểu liệt kê ... những thuộc tính này bao gồm : IsAbstract, IsArray, IsClassembly,IsEnum, IsInterface, IsPointer, IsPrimitive ( 1 trong những kiểu dữ liệu bẩm sinh được định nghĩa trước), IsPublic, IsSealed, and IsValueType. Ví dụ :dùng kiểu dữ liệu bẩm sinh : Type intType = typeof(int);Console.WriteLine(intType.IsAbstract); // writes false Console.WriteLine(intType.IsClassembly); // writes false Console.WriteLine(intType.IsEnum); // writes false Console.WriteLine(intType.IsPrimitive); // writes true Console.WriteLine(intType.IsValueType); // writes true hoặc dùng lớp Vector : Type intType = typeof(Vector);Console.WriteLine(intType.IsAbstract); //writes false Console.WriteLine(intType.IsClassembly); // writes true Console.WriteLine(intType.IsEnum); // writes false Console.WriteLine(intType.IsPrimitive); // writes false Console.WriteLine(intType.IsValueType); // writes false Các phương thức : Hầu hết các phương thức của System.Type được sử dụng để chứa chi tiết các thành viên của kiểu dữ liệu tương ứng - hàm dựng ,thuộc tính,phương thức , biến cố...có nhiều phương thức nhưng tất cả chúng đều theo nền chung. ví dụ , có hai phương thức mà nhận chi tiết phương thức của kiểu dữ liệu : getmethod() và getmethods(). getmethod() trả về 1 tham chiếu đến đối tượng System.Reflection.MethodInfo mà chứa chi tiết của 1 phương thức .getmethods() trả vế 1 mảng tham chiếu. điểm khác là getmethods() trả về chi tiết của tất cả phương thức , trong khi getmethod() trả về chi tiết của chỉ một phương thức được chỉ định trong danh sách thông số.cả hai phương thức đều overloads mà lấy thêm 1 thông số , BindingFlags liệt kê giá trị chỉ định thành viên nào nên được trả về- ví dụ như trả về 1 thành viên public, 1 thành viên instance, thành viên static ... Ví dụ phương thức getmethods() không lấy thông số nào và trả về chi tiết của tất cả phương thức thành viên của kiểu dữ liệu : Type t = typeof(double); MethodInfo [] methods = t.GetMethods(); foreach (MethodInfo nextMethod in methods) { // etc. Kiểu đối tượng trả về Các phương thức (phương thức số nhiều ( có 's' ở cuối tên ) trả về 1 mảng ) ConstructorInfo GetConstructor(), GetConstructors() EventInfo GetEvent(), GetEvents()
  3. Kiểu đối tượng trả về Các phương thức (phương thức số nhiều ( có 's' ở cuối tên ) trả về 1 mảng ) FieldInfo GetField(), GetFields() InterfaceInfo GetInterface(), GetInterfaces() MemberInfo GetMember(), GetMembers() MethodInfo GetMethod(), GetMethods() PropertyInfo GetProperty(), GetProperties() Phương thức getmember() và getmembers() trả về chi tiết của bất kì hay tất cả thành viên của kiểu dữ liệu không cần biết đó là hàm dựng hay thuộc tính phương thức.. Ví dụ TypeView Qua ví dụ này ta có thể đưa ra một danh sách các thành viên của 1 kiểu dữ liệu. ta sẽ minh họa dùng Typeview cho kiểu Double , và có thể thay thế bằng các kiểu khác . typeview trình bày nhiều thông tin hơn trong console window : Hộp thông điệp sẽ trình bày tên , tên đầu đủ namespace của kiểu dữ liệu ... sau đó lặp lại xuyên suốt tất cả các thành viên thể hiện public của kiểu dữ liệu, trình bày mỗi thành viên kiểu khai báo,kiểu thành viên ( phương thức, trường,..) và tên của thành viên.Declaring type là tên của lớp mà thực sự khai báo kiểu thành viên. Để bắt đầu ta thêm vài câu lệnh using: using System; using System.Text; using System.Windows.Forms;
  4. using System.Reflection; Ta cần System.text vì ta dùng Stringbuilder để xây dựng chuỗi trình bày trong message box,và system.windoes.forms cho message box.toàn bộ mã nằm trong mainclassembly, mà có 1 vài phương thức static và 1 trường static, 1 stringbuilder gọi outputText, mà được dùng để tạo chuỗi trình bày trong message box, khai báo như sau : class MainClass { static void Main() { // modify this line to retrieve details of any // other data type Type t = typeof(double); AnalyzeType(t); MessageBox.Show(OutputText.ToString(), "Analysis of type " + t.Name); Console.ReadLine(); } Đầu tiên ta khai báo đối tưọng Type để trình bày kiểu mà ta chọn.sau đó gọi phương thức AnalyzeType(),mà lấy thông tin từ Type và dùng nó làm chuỗi xuất.cuối cùng trình bày nó trong message box. static void AnalyzeType(Type t) { AddToOutput("Type Name: " + t.Name); AddToOutput("Full Name: " + t.FullName); AddToOutput("Namespace: " + t.Namespace); Type tBase = t.BaseType; if (tBase != null) AddToOutput("Base Type:" + tBase.Name); Type tUnderlyingSystem = t.UnderlyingSystemType; if (tUnderlyingSystem != null) AddToOutput("UnderlyingSystem Type:" + tUnderlyingSystem.Name); AddToOutput("\nPUBLIC MEMBERS:"); MemberInfo [] Members = t.GetMembers(); foreach (MemberInfo NextMember in Members) { AddToOutput(NextMember.DeclaringType + " " + NextMember.MemberType + " " + NextMember.Name); } }
  5. Phương thức này gọi những thuộc tính khác nhau của đối tượng Type để lấy thông tin ta cần, liên quan đến tên , sau đó gọi Getmembers() để lấy 1 mảng đối tượng MemberInfo mà ta có thể dùng để trình bày chi tiết của mỗi phưong thức. chú ý rằng ta dùng 1 phương thức trợ giúp , AddTooutput(), để xây dựng chuỗi trình bày. static void AddToOutput(string Text) { OutputText.Append("\n" + Text); } Lớp assembly Lớp assembly được định nghĩa trong namespace System.Reflection , cho phép ta truy xuất vào các metadata trong 1 assembly. Nó cũng chứa những phương thức cho phép ta thực thi 1 assembly,. Như lớp Type, nó chứa 1 số lớn những phương thức và thuộc tính.ta không thể xem xét hết.thay vào đó ta sẽ chỉ tìm hiểu một sồ phưong thức thuộc tính cần thiết. trước khi làm bất cứ điều gì với 1 thể hiện assembly ta cần tải nó vào tiến trình chạy.ta làm điều này bằng cách gọi phương thức static assembly.Load() và assembly.LoadFrom(). điểm khác giữa 2 phương thức là load() lấy tên của assembly,mà phải là assembly được tham chiếu từ assembly đang thực thi đương thời( nói cách khác nó là assembly mà ta tham chiếu khi biên dịch dự án lần đầu.)trong khi loadfrom() lấy đường dẫn của assembly,mà có thể là assembly bất kì được trình bày trong hệ thống : Assembly assembly1 = Assembly.Load("SomeAssembly"); Assembly assembly2 = Assembly.LoadFrom (@"C:\My Projects\GroovySoftware\SomeOtherAssembly"); Có 1 số cách overload khác của 2 phương thức này,mà thêm thông tin bảo mật.mỗi lần ta nạp 1 assembly,ta có thể dùng những thuộc tính khác trên nó để tìm, ví dụ tên đầu đủ của nó : string name = assembly1.FullName; Xem xét các kiểu được định nghĩa trong 1 assembly 1 khía cạnh hay của lớp assembly là nó cho phép ta lấy chi tiết tất cả các kiểu mà được định nghĩa trong assembly tương ứng.ta đơn giản gọi assembly.getTypes() ,trả về 1 mảng System.Type tham chiếu chứa tất cả các kiểu. ta có thể thao tác những tham chiếu kiểu này như đối tượng Type dùng tác tử typeof hoặc Object.Gettype(): Type[] types = theassembly.GetTypes(); foreach(Type definedType in types) DoSomethingWith(definedType); Các thuộc tính tuỳ chọn. Các phương thức ta dùng để tìm những thuộc tính tuỳ chọn được định nghĩa trên 1 assembly hoặc trên kiểu tuỳ thuộc vào kiểu của đối tượng đi kèm.nếu ta muốn tìm những thuộc tính tuỳ chọn đi kèm với 1 assembly ,ta cần gọi phương thức static của lớp attribute, GetCustomAttributes() truyền 1 tham chiếu đến assembly:
  6. Attribute [] definedAttributes = Attribute.GetCustomAttributes(assembly1); // assembly1 là 1 đối tưọng assembly GetCustomAttributes() đưọc dùng để lấy các thuộc tính của assembly, có vài overload : nếu ta gọi không có đặc tả thông số thì nó trả về tất cả các thuộc tính tuỳ chọn được điịnh nghĩa trong assembly đó.ta cũng có thể gọi nó bằng cách chỉ định thông số thứ hai, là 1 đối tưọng Type chỉ định lớp thuộc tính .trong trường hợp này GetCustomAttributes() trả về 1 mảng bao gồm tất cả các thuộc tính trình bày của lớp đó.ta sẽ dùng overload này trong ví dụ WhatsNewAttributes.để tìm các thuộc tính SupportsWhatsNew có được trình bày trong assembly hay không.để làm điều này ta gọi GetCustomAttributes() truyền 1 tham chiếu đến assembly ,và kiểu thuộc tính SupportWhatsNewAttribute .nếu thuộc tính này được trình bày , ta có 1 mảng chứa tất cả các thể hiện của nó.nếu không có trả về null: Attribute supportsAttribute = Attribute.GetCustomAttributes(assembly1, typeof(SupportsWhatsNewAttribute)); Lưu ý tất cả các attribute được lưu như các tham chiếu attribute.nếu ta muốn gọi bất kì phương thức hay thuộc tính nào mà ta đã định nghĩa trong attribute,thì ta sẽ cần ép kiểu những tham chiếu đó tường minh thành những lớp attribute tuỳ chọn có liên quan.ta có thể lấy chi tiết của các attribute tuỳ chọn mà đi kèm với 1 kiểu dữ liệu đã cho bằng cách gọi overload khác của assembly.GetCustomAttributes(), lần này truyền 1 tham chiếu Type mà mô tả kiểu mà ta muốn để lưu bất kì attribute đi kèm.mặt khác nếu ta muốn lấy những attribute mà đi kèm với phương thức,hàm dựng,trường.. thì ta cần gọi GetCustomAttributes() mà là thành viên của 1 trong những lớp MethodInfo,ConstructorInfo, FieldInfo ...phần này nằm ngoài nội dung của chương. Hoàn chỉnh ví dụ WhatsNewAttributes Ta có thể hoàn chỉnh ví dụ này bằng cách viết thêm assembly cuối cùng trong ví dụ assembly LookUpWhatsNew. phần này của ứng dụng là 1 ứng dụng console. tuy nhiên ,nó cần tham chiếu 2 assembly khác . mặc dù ta sắp viết 1 ưng dụng dòng lệnh, nhưng ta sẽ làm theo ví dụ TypeView trước trình bày kết quả trong 1 message box. tập tin được gọi LookUpWhatsNew.cs và lệnh để biên dịch nó là : csc /reference:WhatsNewAttributes.dll /reference:VectorClassembly.dll LookUpWhatsNew.cs Trong phần mã của tập tin này ,đầu tiên ta chỉ định các namespace ta muốn dùng, trong đó có system.Text vì ta cần sử dụng 1 đối tượng Stringbuilder lần nữa: using System; using System.Reflection; using System.Windows.Forms; using System.Text; using Wrox.ProCSharp.VectorClassembly; using Wrox.ProCSharp.WhatsNewAttributes; namespace Wrox.ProCSharp.LookUpWhatsNew
  7. { lớp chính là WhatsNewChecker, mọi phương thức đều được định nghĩa trong lớp này, gồm 2 trường static outputText chứa chuỗi xuất.backDateTo lưu ngày tháng mà ta chọn - tất cả các cập nhật được tạo vào ngày này sẽ được trình bày.. thông thường ta sẽ cho người dùng gõ ngày ,nhưng vì không muốn họ gõ sai nên ta sẽ lấy ngày 1 tháng 2 2002 làm ví dụ. class WhatsNewChecker { static StringBuilder outputText = new StringBuilder(1000); static DateTime backDateTo = new DateTime(2002, 2, 1); static void Main() { Assembly theAssembly = Assembly.Load("VectorClass"); Attribute supportsAttribute = Attribute.GetCustomAttribute( theAssembly, typeof(SupportsWhatsNewAttribute)); string Name = theAssembly.FullName; AddToMessage("Assembly: " + Name); if (supportsAttribute == null) { AddToMessage( "This assembly does not support WhatsNew attributes"); return; } else AddToMessage("Defined Types:"); Type[] types = theAssembly.GetTypes(); foreach(Type definedType in types) DisplayTypeInfo(theAssembly, definedType); MessageBox.Show(outputText.ToString(), "What\'s New since " + backDateTo.ToLongDateString()); Console.ReadLine(); } Đầu tiên main() tải assembly VectorClassembly , xác minh xem nó có thực sự được đánh dấu với attributeSupportsWhatsNew hay không. Giả sử mọi thứ đều đúng ta dùng assembly.GetTypes() để lấy mảng tất cả các kiểu trong assembly này, sau đó lặp qua chúng. trong mỗi lần lặp, ta gọi 1 phương thức mà ta viết DisplayTypeInfo(), mà thêm 1 chuỗi có liên quan, bao gồm chi tiết các thể hiện của
  8. LastModifiedAttribute, thành trường outputText. cuối cùng ta cho hiện message box chuỗi này. phương thức DisplayTypeInfo() như sau: static void DisplayTypeInfo(Assembly theAssembly, Type type) { // make sure we only pick out classes if (!(type.IsClass)) return; AddToMessage("\nclass " + type.Name); Attribute [] attribs = Attribute.GetCustomAttributes(type); if (attribs.Length == 0) AddToMessage("No changes to this class\n"); else foreach (Attribute attrib in attribs) WriteAttributeInfo(attrib); MethodInfo [] methods = type.GetMethods(); AddToMessage("CHANGES TO METHODS OF THIS CLASS:"); foreach (MethodInfo nextMethod in methods) { object [] attribs2 = nextMethod.GetCustomAttributes( typeof(LastModifiedAttribute), false); if (attribs2 != null) { AddToMessage( nextMethod.ReturnType + " " + nextMethod.Name + "()"); foreach (Attribute nextAttrib in attribs2) WriteAttributeInfo(nextAttrib); } } } Lưu ý điều đầu tiên ta làm là kiểm tra tham chiếu Type được truyền vào có thực sự là 1 lớp. bởi vì ta đã chỉ định attributeLastModified chỉ có thể dùng cho lớp hoặc các phương thức thành viên. Kế tiếp ta dùng phương thức Attribute.GetCustomAttributes() để tìm xem nếu lớp có thể hiện LastModifiedAttribute đi kèm với nó hay không.nếu có ta thêm vào chuỗi xuất.dùng phương thức trợ giúp WriteAttributeInfo(). Cuối cùng ta dùng phương thức Type.GetMethods() để lặp tất cả các phương thức thành viên của kiểu dữ liệu này, sau đó làm giống như vậy với mỗi phương thức tiếp theo. Phần mã tiếp theo thể hiện phương thức WriteAttributeInfo() tìm các chuỗi cần trình bày trong thể hiện LastModifiedAttribute , vì phương thức này nhận 1 tham chiếu attribute
  9. nên nó cần được ép kiểu thành tham chiếu LastModifiedAttribute.Sau khi xong dùng các thuộc tính mà ta đã định nghĩa trong attribute này để lấy thông số của nó . nó kiểm tra ngày của attribute trước khi thêm nó vào chuỗi được trình bày: static void WriteAttributeInfo(Attribute attrib) { LastModifiedAttribute lastModifiedAttrib = attrib as LastModifiedAttribute; if (lastModifiedAttrib == null) return; // Kiểm tra ngày tháng hợp lệ DateTime modifiedDate = lastModifiedAttrib.DateModified; if (modifiedDate < backDateTo) return; AddToMessage(" MODIFIED: " + modifiedDate.ToLongDateString() + ":"); AddToMessage(" " + lastModifiedAttrib.Changes); if (lastModifiedAttrib.Issues != null) AddToMessage(" Outstanding issues:" + lastModifiedAttrib.Issues); AddToMessage(""); } Kết quả sau khi chạy :
  10. Lưu ý rằng khi ta liệt kê các kiểu được định nghĩa trong assembly VectorClassembly ta thực sự lấy hai lớp : Vector và lớp VectorEnumerator kèm theo mà ta đã xây dựng trong phần trước. Code for Download: TypeView WhatsNewAttributes
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2