
- C# - Home
- C# - Overview
- C# - Environment
- C# - Program Structure
- C# - Basic Syntax
- C# - Data Types
- C# - Type Conversion
- C# - Variables
- C# - Constants
- C# - Operators
- C# - Arithmetic Operators
- C# - Assignment Operators
- C# - Relational Operators
- C# - Logical Operators
- C# - Bitwise Operators
- C# - Miscellaneous Operators
- C# - Operators Precedence
- C# Conditional Statements
- C# - Decision Making
- C# - If
- C# - If Else
- C# - Nested If
- C# - Switch
- C# - Nested Switch
- C# Control Statements
- C# - Loops
- C# - For Loop
- C# - While Loop
- C# - Do While Loop
- C# - Nested Loops
- C# - Break
- C# - Continue
- C# OOP & Data Handling
- C# - Encapsulation
- C# - Methods
- C# - Nullables
- C# - Arrays
- C# - Strings
- C# - Structure
- C# - Enums
- C# - Classes
- C# - Inheritance
- C# - Polymorphism
- C# - Operator Overloading
- C# - Interfaces
- C# - Namespaces
- C# - Preprocessor Directives
- C# - Regular Expressions
- C# - Exception Handling
- C# - File I/O
- C# Advanced Tutorial
- C# - Attributes
- C# - Reflection
- C# - Properties
- C# - Indexers
- C# - Delegates
- C# - Events
- C# - Collections
- C# - Generics
- C# - Anonymous Methods
- C# - Unsafe Codes
- C# - Multithreading
C# - Reflection
Reflection objects are used for obtaining type information at runtime. The classes that give access to the metadata of a running program are in the System.Reflection namespace.
The System.Reflection namespace contains classes that allow you to obtain information about the application and to dynamically add types, values, and objects to the application.
Applications of Reflection
Reflection has the following applications −
It allows view attribute information at runtime.
It allows examining various types in an assembly and instantiate these types.
It allows late binding to methods and properties
It allows creating new types at runtime and then performs some tasks using those types.
Namespace for Reflection
To use reflection in your C# code, you need to include the System.Reflection namespace. Here is the syntax to include it:
using System.Reflection;
Viewing Metadata
We have mentioned in the preceding chapter that using reflection you can view the attribute information.
The MemberInfo object of the System.Reflection class needs to be initialized for discovering the attributes associated with a class. To do this, you define an object of the target class, as −
System.Reflection.MemberInfo info = typeof(MyClass);
Example 1: Creating and Using Custom Attributes
This C# example, demonstrates how to define and apply a custom attribute using the System.Attribute class −
using System; // Define the custom attribute [AttributeUsage(AttributeTargets.All)] public class HelpAttribute : System.Attribute { public readonly string Url; private string topic; 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; } } // Apply the attribute to a class [Help("Information on the class MyClass", Topic = "Class Info")] class MyClass { } namespace AttributeAppl { class Program { static void Main(string[] args) { System.Reflection.MemberInfo info = typeof(MyClass); object[] attributes = info.GetCustomAttributes(true); foreach (object attr in attributes) { HelpAttribute helpAttr = attr as HelpAttribute; if (helpAttr != null) { Console.WriteLine("Help URL: " + helpAttr.Url); Console.WriteLine("Topic: " + helpAttr.Topic); } } Console.ReadKey(); } } }
When it is compiled and run, it displays the name of the custom attributes attached to the class MyClass −
Help URL: Information on the class MyClass Topic: Class Info
Example 2: Using The DeBugInfo
In this example, we use the DeBugInfo attribute created in the previous chapter and use reflection to read metadata in the Rectangle class.
using System; using System.Reflection; namespace BugFixApplication { //a custom attribute BugFix to be assigned to a 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); //iterating through the attribtues of the 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); } } //iterating through the method attribtues 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 produces 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:
Get Type Info Using Reflection
You can retrieve type metadata using the typeof keyword or the GetType() method.
Example
The following example demonstrates how to get the class name and namespace using reflection:
using System; using System.Reflection; class Person { public int Id { get; set; } public void Greet() { Console.WriteLine("Namaste from Greet!"); } } class Program { static void Main() { Type type = typeof(Person); Console.WriteLine("Class Name: " + type.Name); Console.WriteLine("Namespace: " + type.Namespace); } }
When the above code is compiled and executed, it produces the following result −
Class Name: Person Namespace:
Get Properties, Methods, and Fields
You can also get the class members using reflection:
Example
The following example demonstrates how to list properties, methods, and fields of a class:
using System; using System.Reflection; class Student { public string Name { get; set; } = "Aarav"; public int RollNo { get; set; } = 101; public string School = "Delhi Public School"; public void Introduce() { Console.WriteLine($"Hi, I am {Name}, Roll No: {RollNo}."); } } class Program { static void Main() { Type type = typeof(Student); Console.WriteLine("Properties:"); foreach (var prop in type.GetProperties()) { Console.WriteLine(prop.Name); } Console.WriteLine("Methods:"); foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { Console.WriteLine(method.Name); } Console.WriteLine("Fields:"); foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) { Console.WriteLine(field.Name); } } }
When the above code is compiled and executed, it produces the following result −
Properties: Name RollNo Methods: Introduce Fields: School
Invoke Method Dynamically
You can even invoke methods at runtime by using the reflection.
Example
The following example demonstrates how to invoke a method dynamically using reflection:
using System; using System.Reflection; class Greeter { public void SayHello(string name) { Console.WriteLine($"Hello, {name}!"); } } class Program { static void Main() { Type type = typeof(Greeter); object obj = Activator.CreateInstance(type); MethodInfo method = type.GetMethod("SayHello"); method.Invoke(obj, new object[] { "Ravi" }); } }
When the above code is compiled and executed, it produces the following result −
Hello, Ravi!
Get Assembly Info
You can also retrieve information about assemblies using the reflection.
Example
The following example demonstrates how to get the current assembly name and its defined types:
using System; using System.Reflection; class Program { static void Main() { Assembly assembly = Assembly.GetExecutingAssembly(); Console.WriteLine("Assembly Full Name: " + assembly.FullName); Console.WriteLine("Defined Types:"); foreach (var t in assembly.DefinedTypes) { Console.WriteLine(t.Name); } } }
When the above code is compiled and executed, it produces the following result −
Assembly Full Name: main, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null Defined Types: Program