Introduction
The reflection concept in C# is the ability to inspect the metadata of an assembly at runtime. In other words, assembly content is described by looking at the assembly metadata at runtime by loading a library in memory and reading its attributes.&nIn this article, I'll try to explain reflection concepts and how can it be useful in applications.
When it comes to using reflection in practice scenarios, it is very confusing for the developers to use the reflection concept properly and get benefit from this beautiful feature. However, reflection is not recommended in obvious conditions. It may slow the performance of an application.
What is Reflection in C#?
Reflection is the ability of a managed code to read its own metadata for the purpose of finding assemblies, modules, and type information at runtime. The classes that give access to the metadata of a running program are in System. Reflection.
System. Reflection namespace defines the following types to analyze the module's metadata of an assembly: Assembly, Module, Enum, ParameterInfo, MemberInfo, Type, MethodInfo, ConstructorInfo, FieldInfo, EventInfo, and PropertyInfo.
Assembly Metadata
y is a logical DLL or EXE, which is described by the manifest, the detailed description (metadata) of an assembly. The .NET compiler produces a portable executable PE file for CLR with the extensions of .exe or .dll. This PE file is mainly comprised of metadata and IL (Intermediate Language).
Explanation
When a compiler builds a binary (dll or exe), the code gets compiled into the Intermediate Language (IL) and then packaged in an assembly. An assembly contains metadata which has information about the type of classes and their definitions, including their members, fields, constructors, properties, methods, functions,s, etc.
By using reflection, an assembly can be inspected.
Type _type = Type.GetType("ReflectionConcept.Employee");
// Or
Type _type = typeof(Employee);
Sample Code
using System;
using System.Reflection;
namespace ReflectionConcept
{
public class Employee
{
public int empID { get; set; }
public string empName { get; set; }
public float Salary { get; set; }
public Employee()
{
this.empID = -1;
this.empName = string.Empty;
this.Salary = 0;
}
public Employee(int id, string name, float salary)
{
this.empID = id;
this.empName = name;
this.Salary = salary;
}
public void displayName()
{
Console.WriteLine("Name: " + this.empName);
}
public void printSalary()
{
Console.WriteLine("Salary: " + this.Salary);
}
}
class Program
{
static void Main(string[] args)
{
Type _type = Type.GetType("ReflectionConcept.Employee");
// Type _type = typeof(Employee);
Console.WriteLine(_type.FullName);
Console.WriteLine(_type.Namespace);
Console.WriteLine(_type.Name);
PropertyInfo[] info = _type.GetProperties();
foreach (PropertyInfo propinfo in info)
{
Console.WriteLine(propinfo.Name);
}
MethodInfo[] methods = _
Uses of Reflections
Refection is heavily used by developer IDEs or UI designers such as Visual Studio. The Property window of a .NET application uses reflection to show a list of properties.
still confused; alright, let me take an example of a Web application.
In a Web application, whenever developers drag and drop a control from Toolbox to the Form, the code is written for you. Here reflection plays the role and is used to read control properties and events. These are listed in the Properties window.
Late binding can be achieved by using refection. Meaning reflection gives developers a way to use code that is not available at compile time. By using refection, the new instances of types can be created dynamically, which don’t have information at compile time.
It allows a view of attribute information at runtime.
- It allows for examining various types in an assembly and instantiating these types.
- It allows late binding to methods and properties
- It allows the creation of new types at runtime and then performs some tasks using those types.
Late binding using reflections
Before learning late binding, let us have a look at early binding. Early Binding can be explained in a way that the compiler knows about what kind of objects it is, and what object members and types are. Auto Intellisense is an example where developers can see all available members of a class when typing in the editor.
Employee emp = new Employee();
emp.displayName();
Late binding is nothing but binding at run time. The compiler does not know what kind of object it is or what all the methods and properties it contains. Late binding is achieved by using reflections.
Sample Code
using System;
using System.Reflection;
namespace ReflectionConcept
{
public class Employee
{
public int empID { get; set; }
public string empName { get; set; }
public float Salary { get; set; }
public Employee()
{
this.empID = -1;
this.empName = string.Empty;
this.Salary = 0;
}
public Employee(int id, string name, float salary)
{
this.empID = id;
this.empName = name;
this.Salary = salary;
}
public void displayName()
{
Console.WriteLine("Name: " + this.empName);
}
public void displayemp(string name)
{
Console.WriteLine("Name: " + name);
}
public void printSalary()
{
Console.WriteLine("Salary: " + this.Salary);
}
}
class Program
{
static void Main(string[] args)
{
Assembly exceutable = Assembly.GetExecutingAssembly();
Type Ltype = exceutable.GetType("ReflectionConcept.Employee");
object objEmployee = Activator.CreateInstance(Ltype);
MethodInfo method = Ltype.GetMethod("displayemp");
string[] parameter = new string[1];
parameter[0] = "Abhishek";
string employeeName = (string)method.Invoke(objEmployee, parameter);
Console.ReadLine();
}
}
}
Early Binding Vs Late Binding
- Performance will be good in early binding.
- The application will run faster in early binding since no boxing or unboxing is done here, but in late binding, we need type conversion as it will be decoded at run time.
- Easier to write the code in early binding since the intelligence will be automatically populated
- Less chances errors in early binding, as syntax is checked, which flags errors at compile time itself, but for late binding, there are chances of run time exceptions.
- Late binding would support in all kinds of versions due to handling at run time.
- Minimal Impact of code in future enhancements if late binding is used.
Conclusion
In this article, we've compared early binding and late binding features and found late binding is complex need more lines of code, venerable to run time exceptions, have issues with performance and does not support auto-intellisense in the designer.
So it is very important to understand where late binding should be used. The answer is when we are working with objects that are not available at compile time.