Saturday, 29 November 2014

Code Reflection in C#

This article will introduce you to Code Reflection in C#. While the focus is on C# language here, the concepts can be applied to any technology based on Visual C#, such as ASP.NET, Windows Phone or Windows Store Apps.
This article is also available of the Microsoft TechNet Wiki.

Introduction


Reflection is the ability of a managed code to read its own metadata. 
You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. 
If you are using attributes in your code, reflection enables you to access them.


Uses of Code Reflection

Below are some of the uses of code reflection:

1. Check the type of an object at run-time using MetaData 
2. Examining and instantiating types in an assembly. 
3. Dynamically create type instances and dynamically invoke the methods, fields, properties in created instances. 
4. For performing late binding and accessing methods on types created at run time. 

Classes used in this article


This article makes use the the following classes below

public string Name { getset; }
       public int price{ getset; }
       public List<string> Extras{ getset; }
       public Burger()
       {
           Extras = new List<string>();
       }
   }
   public class Pizza
   {
       public string Name { getset; }
       public int price { getset; }
       public List<string> Toppings { getset; }
       public Pizza()
       {
           Toppings = new List<string>();
       }
       public string cook()
       {
           return "Cooking Pizza " + Name;
       }
       public string cook(string mins)
       {
           return "Cooking Pizza " + Name + " for "+mins+" Mins";
       }
   }

Getting Type data of an Object


To obtain the Type of an object statically at compile time, typeof method can be used. 
  var pizza = new Pizza();
  Type t = typeof(Pizza);

 To obtain the Type of an object dynamically at run time, GetType method can be used. 

  Type t1 = pizza.GetType();
From a Type, several useful information can be obtained about an object, such as its name and assembly. 
 Console.WriteLine(t1.Name); //Pizza
 Console.WriteLine(t1.Assembly); //Reflection, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

Creating an Instance of a type


To create an instance of a type, the method Activator.CreateInstance can be used. This method creates an instance of the specified type using the constructor that best matches the specified parameters. 
Activator.CreateInstance can be used in 2 ways as described below:

a. Creates an instance of the specified type using that type's default constructor.
var newpizza = (Pizza)Activator.CreateInstance(typeof(Pizza));

b. Creates an instance of the type designated by the specified generic type parameter, using the parameterless constructor.

var newpizza1 = (Pizza)Activator.CreateInstance<pizza>();

Example 1: Creating an Object Dynamically.


The example below demonstrates how to create a Pizza object dynamically, retrieve its properties and assign their values.  

Step 1. Creating the instance of the Type Pizza.

var newpizza = (Pizza)Activator.CreateInstance(typeof(Pizza));

Step 2. Retrieving its properties. 
The GetProperties Method, searches for the properties of the current Type, using the specified binding constraints. 

  PropertyInfo[] properties = typeof(Pizza).GetProperties();
 PropertyInfo NameProperty = null;
 PropertyInfo PriceProterty = null;
 PropertyInfo ToppingProperty = null;
  
 foreach (var property in properties)
 {
     if (property.Name.Equals("Name", StringComparison.CurrentCulture))
         NameProperty = property;
     else if (property.Name.Equals("price", StringComparison.CurrentCulture))
         PriceProterty = property;
     else if (property.Name.Equals("Toppings", StringComparison.CurrentCulture))
         ToppingProperty = property;
 }

Step 3: Setting the value of each property.

NameProperty.SetValue(newpizza, "MarlinPizza");
PriceProterty.SetValue(newpizza, 40);
ToppingProperty.SetValue(newpizza, new List<string>() { "cheese""meat" });



Getting the value of a Property from an Object


var HawaiianPizza = new Pizza()
{
    Name = "HawaiianPizza",
    price = 50,
    Toppings = new List<string>(){"cheese","meat"}
};

Step 1: Get the type of the object.

var type = HawaiianPizza.GetType();

Step 2: Get the required property.

var property = type.GetProperty("Name");

Step 3: Get the value of the property.

var value = property.GetValue(HawaiianPizza);//value = "HawaiianPizza"

Invoking methods from an Object


Step 1: Get the type of the object.

var type = HawaiianPizza.GetType();

Step 2: Get the method needed. 
In this example, there 2 methods with the same name. 
To get the method having no parameter, an empty array of type Type should be passed.

var method = type.GetMethod("cook"new Type[] { });

To get the method having a string parameter, pass the parameter in an array like below 

var method = type.GetMethod("cook"new Type[] { typeof(string) });

Step 3: Invoking the method.  
To invoke the method with no parameter, null should be passed to the invoke method. 

var value = (string)method.Invoke(HawaiianPizza,null);

To invoke methods requiring parameters, the parameters can be passed in an array like below 

var value = (string)method.Invoke(HawaiianPizza, new string[] {"5"});

Example 2: A generic method with different behavior based on Object Type


The example below shows how the output can be different on whether a Pizza or a Burger is passed to the PrintReceipt Method. 
    var HawaiianPizza = new Pizza()
    {
        Name = "HawaiianPizza",
        price = 50,
        Toppings = new List<string>() { "cheese""meat" }
    };
    var BigBurger = new Burger()
    {
        Name = "BigBurger",
        price = 100,
        Extras = new List<string>() { "Chips""Cheese" }
    };
    PrintReceipt(HawaiianPizza);
    PrintReceipt(BigBurger);
public static void PrintReceipt(Object obj)
{
    var type = obj.GetType();
    if (type.Name == "Pizza")
    {
        Console.WriteLine("Printing receipt for: " + type.GetProperty("Name").GetValue(obj));
        Console.WriteLine("Toppings: ");
        List<string> toppings = (List<string>)type.GetProperty("Toppings").GetValue(obj);
         
        foreach(var topping in toppings)
            Console.WriteLine(topping);
        Console.WriteLine("Price: " + type.GetProperty("price").GetValue(obj));
     
    }
    if (type.Name == "Burger")
    {
        Console.WriteLine("Printing receipt for: " + type.GetProperty("Name").GetValue(obj));
        Console.WriteLine("Extras: ");
        List<string> toppings = (List<string>)type.GetProperty("Extras").GetValue(obj);
        foreach (var topping in toppings)
            Console.WriteLine(topping);
        Console.WriteLine("Price: " + type.GetProperty("price").GetValue(obj));
     
    }
}

2 comments:

  1. Outstanding quest there. What occurred after? Take care!


    My weblog My Boston SEO company (mybostonseo.com)

    ReplyDelete
  2. Hi.
    Thanks for visiting my blog.
    What do you mean by " What occurred after"?

    ReplyDelete