English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Reflection refers to the ability of a program to access, detect, and modify its own state or behavior.
An assembly contains modules, modules contain types, and types contain members. Reflection provides objects that encapsulate assemblies, modules, and types.
You can use reflection to dynamically create instances of types, bind types to existing objects, or obtain types from existing objects. Then, you can call the methods of the type or access its fields and properties.
Advantages:
1Reflection enhances the flexibility and scalability of the program.
2It reduces coupling and improves adaptability.
3It allows the program to create and control objects of any class without hard-coding the target class in advance.
Disadvantages:
1Performance issues: Using reflection is essentially an interpreted operation, which is much slower than direct code when accessing fields and methods. Therefore, the reflection mechanism is mainly applied to system frameworks with high requirements for flexibility and scalability, and is not recommended for ordinary programs.
2Using reflection can blur the internal logic of the program; programmers hope to see the logic of the program in the source code, but reflection bypasses the technical aspects of the source code, which may bring maintenance issues. Reflection code is more complex than the corresponding direct code.
Reflection has the following uses:
It allows the viewing of attribute information at runtime.
It allows the examination of various types in a collection, as well as instantiating these types.
It allows the late binding of methods and properties.
It allows the creation of new types at runtime and then executing tasks with these types.
We have mentioned in the previous chapter that reflection can be used to view attribute information.
System.Reflection of the class MemberInfo An object needs to be initialized to discover attributes related to the class. To do this, you can define an object of the target class, as follows:
System.Reflection.MemberInfo info = typeof(MyClass);
The following program demonstrates this:
using System; [AttributeUsage(AttributeTargets.All)] public class HelpAttribute : System.Attribute { public readonly string Url; public string Topic // Topic is a named parameter { get { return topic; } set { topic = value; } } public HelpAttribute(string url) // url is a positional parameter { this.Url = url; } private string topic; } [HelpAttribute("Information on the class MyClass")] class MyClass { } namespace AttributeAppl { class Program { static void Main(string[] args) { System.Reflection.MemberInfo info = typeof(MyClass); object[] attributes = info.GetCustomAttributes(true); for (int i = 0; i < attributes.Length; i++) { System.Console.WriteLine(attributes[i]); } Console.ReadKey(); } } }
When the above code is compiled and executed, it will display the attributes attached to the class MyClass with the custom attribute:
HelpAttribute
In this example, we will use the one created in the previous chapter DeBugInfo features, and use reflection (Reflection) to read Rectangle Metadata in the class.
using System; using System.Reflection; namespace BugFixApplication { // A custom attribute BugFix is assigned to the class and its members [AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = true)] public class DeBugInfo : System.Attribute { private int bugNo; private string developer; private string lastReview; public string message; public DeBugInfo(int bg, string dev, string d) { this.bugNo = bg; this.developer = dev; this.lastReview = d; } public int BugNo { get { return bugNo; } } public string Developer { get { return developer; } } public string LastReview { get { return lastReview; } } public string Message { get { return message; } set { message = value; } } } [DeBugInfo(45, "Zara Ali", "12/8/2012" Message = "Return type mismatch")] [DeBugInfo(49, "Nuha Ali", "10/10/2012" Message = "Unused variable")] class Rectangle { // Member variables protected double length; protected double width; public Rectangle(double l, double w) { length = l; width = w; } [DeBugInfo(55, "Zara Ali", "19/10/2012" Message = "Return type mismatch")] public double GetArea()} { return length * width; } [DeBugInfo(56, "Zara Ali", "19/10/2012)] public void Display() { Console.WriteLine("Length: {0}", length); Console.WriteLine("Width: {0}", width); Console.WriteLine("Area: {0}", GetArea()); } }//end class Rectangle class ExecuteRectangle { static void Main(string[] args) { Rectangle r = new Rectangle(4.5, 7.5); r.Display(); Type type = typeof(Rectangle); // Traverse attributes of Rectangle class foreach (Object attributes in type.GetCustomAttributes(false)) { DeBugInfo dbi = (DeBugInfo)attributes; if (null != dbi) { Console.WriteLine("Bug no: {0}", dbi.BugNo); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } // Traverse method attributes foreach (MethodInfo m in type.GetMethods()) { foreach (Attribute a in m.GetCustomAttributes(true)) { DeBugInfo dbi = (DeBugInfo)a; if (null != dbi) { Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name); Console.WriteLine("Developer: {0}", dbi.Developer); Console.WriteLine("Last Reviewed: {0}", dbi.LastReview); Console.WriteLine("Remarks: {0}", dbi.Message); } } } Console.ReadLine(); } } }
When the above code is compiled and executed, it will produce the following result:
Length: 4.5 Width: 7.5 Area: 33.75 Bug No: 49 Developer: Nuha Ali Last Reviewed: 10/10/2012 Remarks: Unused variable Bug No: 45 Developer: Zara Ali Last Reviewed: 12/8/2012 Remarks: Return type mismatch Bug No: 55, for Method: GetArea Developer: Zara Ali Last Reviewed: 19/10/2012 Remarks: Return type mismatch Bug No: 56, for Method: Display Developer: Zara Ali Last Reviewed: 19/10/2012 Remarks: