Reflection in .Net

Introduction

Refelection allows you to write code that can inspect various aspects about the code itself. It enables you to do simple things like:

  •  Check the type of an object at runtime (simple calls to typeof() for example).
  • Inspect the Attributes of an object at runtime to change the behavior of a method (The various serialization methods in.Net).
  • Loading an assembly at runtime, finding a specific class, determining if it matches a given interface, and invoking certain members dynamically.
  • Provide dynamically metadata information about an object, for exmaple it can be used by Web Services when the client cosnumes a web service, where a proxy class

will be generated from such client. this proxy is generated from a WSDL document, and that most often is generated from type metadata generated via refelction.

  • Reflection helps us to browse methods, properties, and function of a given class or assembly on run time. You can also invoke the methods, and functions using refelection.

 Most common typical -used tools associated with .Net reflection are:

  • The Type class and its related members
  • Assembly class and its related members

 If you declare a reference type variable and instantiate it in the application, the system will in the application heap allocate related memory, create the object instance, and then return the memory address of the instance to the variable.

So, you see, the variable holds the memory address, which is equivalent to a pointer in C++. Declare a variable of a value type, however, will result in allocating it in the thread stack. In this case, the variable itself contains all the fields of the value type.

When we need to compare whether two objects are equal. When we compare two reference typed variables, what we compare is in fact whether these two variables point to the same instance in the heap. When we compare two variables of value type, because the variable itself contains all types of fields (data), during the course of comparison we need make a field-for-field comparison with these two variables to see whether the value of each field is equal.

If the value of any field is different, then we conclude these two variables are not equal and return false. All value types inherit from System.ValueType. ValueType and all types in turn inherit from System.Object. Object offers a Equals() method, used to determine whether two objects are equal. Please do bear in mind that ValueType overrides the Equals() method of Object. When we compare whether two value typed variables are equal, we can call the Equals() method inherited from the ValueType type.

EX.

public struct ValPoint

{

   public int x;

   public int y;

}

static void Main(string[] args)

{

   bool result;

   ValPoint A1;

   A1.x = A1.y = 3;

   ValPoint B1=A1;  //copy the value of A to B

   result = A1.Equals(B1);

   Console.WriteLine(result);  //output True;

}

NOTE

Using the Equals() method towards the value type will be very expensive, and as such Reflection should be used to obtain the basic types associated information.

 The role of reflection

reflection provides the following capabilities:

  •  View and traverse the information of the basic types (and their members) and the metadata inside assemblies;
  • Late bind methods and properties;
  • Dynamically create type instances (and can dynamically invoke the methods, fields, properties in created instances).

 Type Object

Type class plays the core role in .Net reflection, which not only encapsulates information about the objects, but also is the entrance of refelection. As soon as you get the Type object of a specified type, you can acquire all the information (methods, fields, properties, events, parameters, constructors, etc.) of this type using the properties and methods provided by the Type object.

To do this, the first step is to get the Type instance of a specified type, and there are two forms to get the type object:

1-Use the static method GetType() provided by the Type class:

EX.

Type t = Type.GetType(“System.IO.Stream”);

txtOutput.Text = t.ToString();

2- Use the typeof Operator:

EX.

Type t = typeof(System.IO.Stream);

3-Obtain the Type object throug instance of a type

String name = “Hello reflection!”;

Type t = name.GetType();

 EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace RefelectionProject4

{

    class Program

    {

        static void Main(string[] args)

        {

            String name = “Hello reflection!”;

            Type t = name.GetType();

            Console.WriteLine(“This is the output {0}”, t);

            Console.ReadKey();

        }

    }

}

Type Object

Type is an abstract class defined in the namespace “System.Type” inside the assembly mscorlib. It provides plenty of properties, used to obtain the basic information of related type. Commonly-used properties are the following:

 

Attribute

Description

Name   Returns the name of the member. In the case of a nested type, Name returns the concatenation of the name of the containing type, followed by ‘+’, followed by the name of the nested type.
FullName Gets the fully qualified name of the Type, including the namespace of the Type but not the assembly.
Namespace Gets the namespace of the Type.
BaseType  Gets the type from which the current Type directly inherits.
UnderlyingSystemType   Indicates the type provided by the common language runtime that represents this type.
Attributes Gets the attributes associated with the Type.
IsValueType    Gets a value indicating whether the Type is a value type.
IsByRef            Gets a value indicating whether the Type is passed by reference.
IsEnum            Gets a value indicating whether the current Type represents an enumeration.
IsClass Gets a value indicating whether the Type is a class; that is, not a value type or interface.
IsInterface Gets a value indicating whether the Type is an interface; that is, not a class or a value type.
IsSealed Gets a value indicating whether the Type is declared sealed.
IsPrimitive Gets a value indicating whether the Type is one of the primitive types.
IsAbstract Gets a value indicating whether the Type is abstract and must be overridden.
IsPublic Gets a value indicating whether the Type is declared public.
IsNotPublic Gets a value indicating whether the Type is not declared public.
IsVisible Gets a value indicating whether the Type can be accessed by code outside the assembly.

 EX.

//Somewhere in front of this point demo has been instantiated

Type t = demo.GetType();

The basic information that you can get from the GetType() static method is the following data:

  •  What type does demo belong to (demo related type name)”
  • What namespace does this type in?
  • What are its base type and its mapping type in .Net runtime library?
  • Is it a value type or reference type?
  • Is it public?
  • Is it a type of enumeration, calss, array, or inteface?
  • Is it a base type (such as int, double, etc.)?

 Refelect Assembly Info

In .Net, the assembly is the basic unit for employment and version control, which contains the relevant modules and types. In the System.Refelection namespace there is defined an Assembly class, which represnts an assembly and includes information about the assembly.

When the assembly is loaded in the program, we can use he two static methods provided by Assemby: LoadFrom() and Load():

EX.

When using the LoadFrom(0 method, you can only supply the file na,e of the assembly (*.dll), and the prerequisite is you have referenced the assembly to the project.

 Assembly asm = Assembly.LoadFrom(“Dem.dll”);

 OR

 Assembly asm = Assembly.Load(“Demo”);

NOTE

  • If you want to load an assembly belonging to the current project, you need to give the full path such as:

 Assembly asm1 =Assembly.LoadFrom(@”C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll”);

  •  When using the Load() method, you can only provide the assembly name, without the suffix.
  •  If you want to get the current assembly, you can use the static method “GetExecutingAssembly” of class assembly, which returns the current executing code related assembly (that is, the current assembly).

Assembly as = Assembly.GetExecutingAssembly();

 The following are the most commonly used members provided by the assembly class:

 

Attribute/method

Description

FullName assembly name.
Location the assembly path.
GetTypes() get all types contained inside the assembly.
GetType() obtain a specified type.
GetModules() get all modules contained inside the assembly.
GetModule() obtain a specified module.
GetCustomAttributes() get info about customized attributes.

 EX.

The following example will referenc the class library “Demo” within the Console application:

 Class library “Demo”

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Demo

{

    public abstract class BaseClass{}

    public struct DemoStruct { }

    public delegate void DemoDelegate(Object sender, EventArgs e);

    public enum DemoEnum

    {

       terrible, bad, common = 4, good, wonderful = 8

    }

    public interface IDemoInterface

    {

      void SayGreeting(string name);

    }

    public interface IDemoInterface2 { }

    public sealed class DemoClass : BaseClass, IDemoInterface, IDemoInterface2

    {

      private string name;

      public string city;

      public readonly string title;

      public const string text = “Const Field”;

      public event DemoDelegate myEvent;

      public string Name

      {

         private get { return name; }

         set { name = value; }

      }

      public DemoClass()

      {

          title = “Readonly Field”;

      }

      public class NestedClass { }

      public void SayGreeting(string name)

      {

         Console.WriteLine(“Morning :” + name);

      }

    }

  }

Console Application

using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

        public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

             foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

        }

    }

}

EX.

MyClass objMyClass = new MyClass();

// Get the class type

Type parameterType = objMyClass.GetType();

 string name = parameterType.Name;

// Browse through members

foreach (MemberInfo objMemberInfo in parameterType.GetMembers())

{

            Console.WriteLine(objMemberInfo.Name);

}

// Browse through properties.

foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties())

{

            Console.WriteLine(objPropertyInfo.Name);

}

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

namespace RefeletionProject

{

    class MyClass

    {

        public void Example(int property)

        {

            Property = property;

        }

        public int Property { get; private set; }

    }

     class Program

    {

        static void Main(string[] args)

        {

            MyClass objMyClass = new MyClass();

            // Get the class type

            Type parameterType = objMyClass.GetType();

             string name = parameterType.Name;

            // Browse through members

            foreach (MemberInfo objMemberInfo in parameterType.GetMembers())

            {

                Console.WriteLine(objMemberInfo.Name);

            }

            // Browse through properties.

            foreach (PropertyInfo objPropertyInfo in parameterType.GetProperties())

            {

                Console.WriteLine(objPropertyInfo.Name);

            }

            Console.ReadKey();

        }

    }

}

EX.

using System;

using System.Reflection;

 namespace ReflectionQueryTest

{

     public class TestBaseClass { }

     public class TestDerivedClass : TestBaseClass { }

    struct TestStruct { }

     interface TestInterface { }

     class TestAttribute : System.Attribute { }

    enum TestEnum { }

    class Class1

    {

        private static void ReflectType(string sTypeName)

    {

    try

    {

    // get the type from the given string

    Type type = Type.GetType(sTypeName);

     Console.WriteLine(“Type name: {0}”, type.FullName);

    Console.WriteLine(“\tHasElementType = {0}”,

    type.HasElementType);

    Console.WriteLine(“\tIsAbstract = {0}”,

    type.IsAbstract);

    Console.WriteLine(“\tIsAnsiClass = {0}”,

    type.IsAnsiClass);

    Console.WriteLine(“\tIsArray = {0}”, type.IsArray);

     }

    catch (System.NullReferenceException)

    {

    Console.WriteLine(“{0} is not a valid type”, sTypeName);

    }

    }

         static void Main(string[] args)

        {

            // Reflect all the attributes for the given type by

            // passing the name of the type

            ReflectType(“System.Int32”);

            ReflectType(“ReflectionQueryTest.TestDerivedClass”);

            ReflectType(“ReflectionQueryTest.TestStruct”);

            ReflectType(“ReflectionQueryTest.TestBaseClass”);

             ReflectType(“ReflectionQueryTest.TestInterface”);

            ReflectType(“ReflectionQueryTest.TestAttribute”);

            ReflectType(“ReflectionQueryTest.TestEnum”);

            Console.ReadKey();

        }

     }

}

 In the previous examples, we’re able to get all types inside an assmbly, however, the output results only list the type’s full name. In real cases, we often need more detailed information abou the type.

 

EX.

The following exmaple includes another method called named “TypeExplor2”, used to obtain detailed information of the specified type:

  using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

          public static void TypeExplore2 (Type t)

        {

             StringBuilder sb = new StringBuilder ();

            sb.Append (“Name Information: \n”);

            sb.Append (“Name:” +t.Name +”\n”);

            sb.Append (“FullName:”+ t.FullName+ “\n”);

            sb.Append (“Namespace:”+ t.Namespace+ “\n”);

            sb.Append (“\n Other information: \n”);

            sb.Append (“BaseType (base type):”+ t.BaseType+ “\n”);

            sb.Append (“UnderlyingSystemType:” +t.UnderlyingSystemType+ “\n”);

            sb.Append (“\n type information: \n”);

            sb.Append (“Attributes (TypeAttributes bit tag):”+ t.Attributes+ “\n”);

            sb.Append (“IsValueType (value type):” +t.IsValueType+ “\n”);

            sb.Append (“IsEnum (enum):”+ t.IsEnum+ “\n”);

            sb.Append (“IsClass (Class):”+ t.IsClass +”\n”);

            sb.Append (“IsArray (array):” +t.IsArray+ “\n”);

            sb.Append(“IsInterface (Interface):” + t.IsInterface + “\n”);

            sb.Append (“IsPointer (pointer):” +t.IsPointer+ “\n”);

            sb.Append (“IsSealed (seal):” +t.IsSealed+ “\n”);

            sb.Append (“IsPrimitive (base type):” +t.IsPrimitive+ “\n”);

            sb.Append (“IsAbstract (abstract):” +t.IsAbstract+ “\n”);

            sb.Append (“IsPublic (open):” +t.IsPublic+ “\n”);

            sb.Append (“IsNotPublic (private):” +t.IsNotPublic+ “\n”);

            sb.Append (“IsVisible:” +t.IsVisible+ “\n”);

            sb.Append (“IsByRef (pass by reference):” +t.IsByRef+ “\n”);

            Console.WriteLine(sb.ToString ());

        }

        public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

              foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

            Type t = typeof(Demo.DemoClass);

            TypeExplore2(t);

            Console.ReadKey();

        }

    }

}

 Member Information and the MemberInfo Type

 The MemberInfo calss represents the member type of Type. The class Type itself is inherited from the MemberInfo class. Class Type provides a few methods, such as  “GetMembers(), GetMember(), FindMember(), etc.”

EX.

The following example used the GetMembers() method to get an array of the members information, then traversed the array, outputing the name and type of memebers.

using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

        public static void MemberExplore3(Type t)

        {

          StringBuilder sb = new StringBuilder();

          MemberInfo[] memberInfo = t.GetMembers();

          sb.Append(“View Type”+ t.Name+ “members of the message: \n”);

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append (“members:” +mi.ToString().PadRight (40) +”Type:” +mi.MemberType +”\n”);

            }

               Console.WriteLine(sb.ToString());

        }

         public static void TypeExplore2 (Type t)

        {

             StringBuilder sb = new StringBuilder ();

            sb.Append (“Name Information: \n”);

            sb.Append (“Name:” +t.Name +”\n”);

            sb.Append (“FullName:”+ t.FullName+ “\n”);

            sb.Append (“Namespace:”+ t.Namespace+ “\n”);

            sb.Append (“\n Other information: \n”);

            sb.Append (“BaseType (base type):”+ t.BaseType+ “\n”);

            sb.Append (“UnderlyingSystemType:” +t.UnderlyingSystemType+ “\n”);

            sb.Append (“\n type information: \n”);

            sb.Append (“Attributes (TypeAttributes bit tag):”+ t.Attributes+ “\n”);

            sb.Append (“IsValueType (value type):” +t.IsValueType+ “\n”);

            sb.Append (“IsEnum (enum):”+ t.IsEnum+ “\n”);

            sb.Append (“IsClass (Class):”+ t.IsClass +”\n”);

            sb.Append (“IsArray (array):” +t.IsArray+ “\n”);

            sb.Append(“IsInterface (Interface):” + t.IsInterface + “\n”);

            sb.Append (“IsPointer (pointer):” +t.IsPointer+ “\n”);

            sb.Append (“IsSealed (seal):” +t.IsSealed+ “\n”);

            sb.Append (“IsPrimitive (base type):” +t.IsPrimitive+ “\n”);

            sb.Append (“IsAbstract (abstract):” +t.IsAbstract+ “\n”);

            sb.Append (“IsPublic (open):” +t.IsPublic+ “\n”);

            sb.Append (“IsNotPublic (private):” +t.IsNotPublic+ “\n”);

            sb.Append (“IsVisible:” +t.IsVisible+ “\n”);

            sb.Append (“IsByRef (pass by reference):” +t.IsByRef+ “\n”);

            Console.WriteLine(sb.ToString ());

        }

        public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

              foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

            Type t = typeof(Demo.DemoClass);

            TypeExplore2(t);

            Console.ReadKey();

            MemberExplore3(typeof(Demo.DemoClass));

            Console.ReadKey();

        }

    }

}

Sometimes we may not want to see the base class members, while at other times we may also want to obtain the private members. In these cases, you can use the overloaded versions of the GetMembers() method, with the bit flags BindingFlags passed as parameter.

BindingFlags is used to decide how to get  members, for example, if we want to get all of the public, private, static, and instance memebers, we only need to modify the “GetMembers()” method as follows:

EX.

MemberInfo [] memberInfo = t.GetMembers (BindingFlags.Public |

BindingFlags.Static |

BindingFlags.NonPublic |

BindingFlags.Instance |

BindingFlags.DeclaredOnly

);

If you want to get all the methods, we can use the FindMembers() method of class Type as follows:

EX.

The “Type.FilterName” in this example returns an instance of the MemberFilter type, which indicates to filter  according to the method name. The last argument “*” indicates to return all the names:

 MemberInfo [] memberInfo = t.FindMembers(MemberTypes.Method, //the searched members are of Method type

BindingFlags.Public |

BindingFlags.Static |

BindingFlags.NonPublic |

BindingFlags.Instance |

BindingFlags.DeclaredOnly,

Type.FilterName,”*”);

Field Information and the FieldInfo Type

MemberInfo is a base class that contains the public information of various members of a specified type. .Net  provides a FieldInfo type to encapsulate the fields, which is derived from MemberInfo, for example, if you want to  get all the fields of some type, you can use the “GetFields()” method:

 EX.

public static void FieldExplore (Type t)

{

            StringBuilder sb = new StringBuilder();

            FieldInfo [] fields = t.GetFields();

            sb.Append (“View Type” +t.Name+ “field information: \n”);

            sb.Append (String.Empty.PadLeft(50, ‘-‘) +”\n”);

            foreach (FieldInfo fi in fields)

        {

                        sb.Append (“Name:” +fi.Name+ “\n”);

                        sb.Append (“Type:” +fi.FieldType+ “\n”);

                        sb.Append (“attribute:” +fi.Attributes+ “\n\n”);

        }

                        Console.WriteLine(sb.ToString ());

}

EX.

using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

        public static void FieldExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            FieldInfo[] fields = t.GetFields();

            sb.Append(“View Type” + t.Name + “field information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            foreach (FieldInfo fi in fields)

            {

                sb.Append(“Name:” + fi.Name + “\n”);

                sb.Append(“Type:” + fi.FieldType + “\n”);

                sb.Append(“attribute:” + fi.Attributes + “\n\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        public static void MemberExplore3(Type t)

        {

          StringBuilder sb = new StringBuilder();

          MemberInfo[] memberInfo = t.GetMembers();

          sb.Append(“View Type”+ t.Name+ “members of the message: \n”);

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append (“members:” +mi.ToString().PadRight (40) +”Type:” +mi.MemberType +”\n”);

            }

               Console.WriteLine(sb.ToString());

        }

         public static void TypeExplore2 (Type t)

        {

             StringBuilder sb = new StringBuilder ();

            sb.Append (“Name Information: \n”);

            sb.Append (“Name:” +t.Name +”\n”);

            sb.Append (“FullName:”+ t.FullName+ “\n”);

            sb.Append (“Namespace:”+ t.Namespace+ “\n”);

            sb.Append (“\n Other information: \n”);

            sb.Append (“BaseType (base type):”+ t.BaseType+ “\n”);

            sb.Append (“UnderlyingSystemType:” +t.UnderlyingSystemType+ “\n”);

            sb.Append (“\n type information: \n”);

            sb.Append (“Attributes (TypeAttributes bit tag):”+ t.Attributes+ “\n”);

            sb.Append (“IsValueType (value type):” +t.IsValueType+ “\n”);

            sb.Append (“IsEnum (enum):”+ t.IsEnum+ “\n”);

            sb.Append (“IsClass (Class):”+ t.IsClass +”\n”);

            sb.Append (“IsArray (array):” +t.IsArray+ “\n”);

            sb.Append(“IsInterface (Interface):” + t.IsInterface + “\n”);

            sb.Append (“IsPointer (pointer):” +t.IsPointer+ “\n”);

            sb.Append (“IsSealed (seal):” +t.IsSealed+ “\n”);

            sb.Append (“IsPrimitive (base type):” +t.IsPrimitive+ “\n”);

            sb.Append (“IsAbstract (abstract):” +t.IsAbstract+ “\n”);

            sb.Append (“IsPublic (open):” +t.IsPublic+ “\n”);

            sb.Append (“IsNotPublic (private):” +t.IsNotPublic+ “\n”);

            sb.Append (“IsVisible:” +t.IsVisible+ “\n”);

            sb.Append (“IsByRef (pass by reference):” +t.IsByRef+ “\n”);

            Console.WriteLine(sb.ToString ());

        }

         public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

            foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

            Type t = typeof(Demo.DemoClass);

            TypeExplore2(t);

            Console.ReadKey();

            MemberExplore3(typeof(Demo.DemoClass));

            Console.ReadKey();

             FieldExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

       }

    }

}

NOTE

  • The property “fi.FieldType” returns a big tag called “FieldAttributes” which contains the attribute information of the field.
  • Class FieldInfo provides a set of attributes to return the bool tyoe, to illustrate the target field related information, the common used attributes are: IsPublic, IsStatic, IsInitOnly, Isliteral, IsPrivate, and so on.

Attribute Information and the Property Type

Similar to fields, you can also through the “GetProperty()” method, which acquires all the propeorty information of the target type:

EX.

public static void PropertyExplore (Type t)

{

            StringBuilder sb = new StringBuilder ();

            sb.Append (“View Type”+ t.Name +”attribute information: \n”);

            sb.Append (String.Empty.PadLeft (50, ‘-‘)+ “\n”);

            PropertyInfo [] properties = t.GetProperties ();

            foreach (PropertyInfo pi in properties)

            {

                        sb.Append (“Name:” +pi.Name+ “\n”);

                        sb.Append (“Type:” +pi.PropertyType+ “\n”);

                        sb.Append (“read:” +pi.CanRead+ “\n”);

                        sb.Append (“write:” +pi.CanWrite+ “\n”);

                        sb.Append (“attribute:” +pi.Attributes+ “\n”);

            }

                        Console.WriteLine (sb.ToString ());

}

EX.

using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

        public static void PropertyExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append(“View Type” + t.Name + “attribute information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            PropertyInfo[] properties = t.GetProperties();

             foreach (PropertyInfo pi in properties)

            {

                sb.Append(“Name:” + pi.Name + “\n”);

                sb.Append(“Type:” + pi.PropertyType + “\n”);

                sb.Append(“read:” + pi.CanRead + “\n”);

                sb.Append(“write:” + pi.CanWrite + “\n”);

                sb.Append(“attribute:” + pi.Attributes + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        public static void FieldExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            FieldInfo[] fields = t.GetFields();

            sb.Append(“View Type” + t.Name + “field information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            foreach (FieldInfo fi in fields)

            {

                sb.Append(“Name:” + fi.Name + “\n”);

                sb.Append(“Type:” + fi.FieldType + “\n”);

                sb.Append(“attribute:” + fi.Attributes + “\n\n”);

            }

            Console.WriteLine(sb.ToString());

        }

         public static void MemberExplore3(Type t)

        {

          StringBuilder sb = new StringBuilder();

          MemberInfo[] memberInfo = t.GetMembers();

          sb.Append(“View Type”+ t.Name+ “members of the message: \n”);

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append (“members:” +mi.ToString().PadRight (40) +”Type:” +mi.MemberType +”\n”);

            }

               Console.WriteLine(sb.ToString());

        }

        public static void TypeExplore2 (Type t)

        {

             StringBuilder sb = new StringBuilder ();

            sb.Append (“Name Information: \n”);

            sb.Append (“Name:” +t.Name +”\n”);

            sb.Append (“FullName:”+ t.FullName+ “\n”);

            sb.Append (“Namespace:”+ t.Namespace+ “\n”);

            sb.Append (“\n Other information: \n”);

            sb.Append (“BaseType (base type):”+ t.BaseType+ “\n”);

            sb.Append (“UnderlyingSystemType:” +t.UnderlyingSystemType+ “\n”);

            sb.Append (“\n type information: \n”);

            sb.Append (“Attributes (TypeAttributes bit tag):”+ t.Attributes+ “\n”);

            sb.Append (“IsValueType (value type):” +t.IsValueType+ “\n”);

            sb.Append (“IsEnum (enum):”+ t.IsEnum+ “\n”);

            sb.Append (“IsClass (Class):”+ t.IsClass +”\n”);

            sb.Append (“IsArray (array):” +t.IsArray+ “\n”);

            sb.Append(“IsInterface (Interface):” + t.IsInterface + “\n”);

            sb.Append (“IsPointer (pointer):” +t.IsPointer+ “\n”);

            sb.Append (“IsSealed (seal):” +t.IsSealed+ “\n”);

            sb.Append (“IsPrimitive (base type):” +t.IsPrimitive+ “\n”);

            sb.Append (“IsAbstract (abstract):” +t.IsAbstract+ “\n”);

            sb.Append (“IsPublic (open):” +t.IsPublic+ “\n”);

            sb.Append (“IsNotPublic (private):” +t.IsNotPublic+ “\n”);

            sb.Append (“IsVisible:” +t.IsVisible+ “\n”);

            sb.Append (“IsByRef (pass by reference):” +t.IsByRef+ “\n”);

            Console.WriteLine(sb.ToString ());

        }

         public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

          foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

           Type t = typeof(Demo.DemoClass);

            TypeExplore2(t);

            Console.ReadKey();

 

            MemberExplore3(typeof(Demo.DemoClass));

            Console.ReadKey();

             FieldExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

             PropertyExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

         }

    }

}

Method Information and the MethodInfo Type

Similar to the previous exmaples, class “MethodInfo” also has an “Attributes” property, which returns  a “MethodAttribute”. MethodAttribute owns a set of bit flags, indicating some properties of the method  such as “Abstract”, “Static”, “Virtual”, “Public”, “Private”, and so on.

The difference from the preceding examples lies in that methods can have parameters and returned values.Class “MethodInfo” provides a “GetParameters()” method to get an array of parameter objects. The method related parameters are all encapsulated in the “ParameterInfo” type.

EX.

public static void MethodExplore (Type t)

{

            StringBuilder sb = new StringBuilder ();

            sb.Append (“View Type” +t.Name+ “means information: \n”);

            sb.Append (String.Empty.PadLeft (50, ‘-‘) +”\n”);

            MethodInfo [] methods = t.GetMethods ();

            foreach (MethodInfo method in methods)

            {

                        sb.Append (“Name:” +method.Name +”\n”);

                        sb.Append (“Signature:” +method.ToString() +”\n”);

                        sb.Append (“attribute:” +method.Attributes +”\n”);

                        sb.Append (“return type:” +method.ReturnType +”\n\n”);

            }

            Console.WriteLine (sb.ToString ());

}

EX.

using System;

using System.Reflection;

using System.Text;

namespace ReflectAssembly

{

    class Program

    {

        public static void MethodExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append(“View Type” + t.Name + “means information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            MethodInfo[] methods = t.GetMethods();

             foreach (MethodInfo method in methods)

            {

                sb.Append(“Name:” + method.Name + “\n”);

                sb.Append(“Signature:” + method.ToString() + “\n”);

                sb.Append(“attribute:” + method.Attributes + “\n”);

                sb.Append(“return type:” + method.ReturnType + “\n\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        public static void PropertyExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append(“View Type” + t.Name + “attribute information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            PropertyInfo[] properties = t.GetProperties();

             foreach (PropertyInfo pi in properties)

            {

                sb.Append(“Name:” + pi.Name + “\n”);

                sb.Append(“Type:” + pi.PropertyType + “\n”);

                sb.Append(“read:” + pi.CanRead + “\n”);

                sb.Append(“write:” + pi.CanWrite + “\n”);

                sb.Append(“attribute:” + pi.Attributes + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

         public static void FieldExplore(Type t)

        {

            StringBuilder sb = new StringBuilder();

            FieldInfo[] fields = t.GetFields();

            sb.Append(“View Type” + t.Name + “field information: \n”);

            sb.Append(String.Empty.PadLeft(50, ‘-‘) + “\n”);

            foreach (FieldInfo fi in fields)

            {

                sb.Append(“Name:” + fi.Name + “\n”);

                sb.Append(“Type:” + fi.FieldType + “\n”);

                sb.Append(“attribute:” + fi.Attributes + “\n\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        public static void MemberExplore3(Type t)

        {

          StringBuilder sb = new StringBuilder();

          MemberInfo[] memberInfo = t.GetMembers();

          sb.Append(“View Type”+ t.Name+ “members of the message: \n”);

            foreach (MemberInfo mi in memberInfo)

            {

                sb.Append (“members:” +mi.ToString().PadRight (40) +”Type:” +mi.MemberType +”\n”);

            }

               Console.WriteLine(sb.ToString());

        }

         public static void TypeExplore2 (Type t)

        {

             StringBuilder sb = new StringBuilder ();

            sb.Append (“Name Information: \n”);

            sb.Append (“Name:” +t.Name +”\n”);

            sb.Append (“FullName:”+ t.FullName+ “\n”);

            sb.Append (“Namespace:”+ t.Namespace+ “\n”);

            sb.Append (“\n Other information: \n”);

            sb.Append (“BaseType (base type):”+ t.BaseType+ “\n”);

            sb.Append (“UnderlyingSystemType:” +t.UnderlyingSystemType+ “\n”);

            sb.Append (“\n type information: \n”);

            sb.Append (“Attributes (TypeAttributes bit tag):”+ t.Attributes+ “\n”);

            sb.Append (“IsValueType (value type):” +t.IsValueType+ “\n”);

            sb.Append (“IsEnum (enum):”+ t.IsEnum+ “\n”);

            sb.Append (“IsClass (Class):”+ t.IsClass +”\n”);

            sb.Append (“IsArray (array):” +t.IsArray+ “\n”);

            sb.Append(“IsInterface (Interface):” + t.IsInterface + “\n”);

            sb.Append (“IsPointer (pointer):” +t.IsPointer+ “\n”);

            sb.Append (“IsSealed (seal):” +t.IsSealed+ “\n”);

            sb.Append (“IsPrimitive (base type):” +t.IsPrimitive+ “\n”);

            sb.Append (“IsAbstract (abstract):” +t.IsAbstract+ “\n”);

            sb.Append (“IsPublic (open):” +t.IsPublic+ “\n”);

            sb.Append (“IsNotPublic (private):” +t.IsNotPublic+ “\n”);

            sb.Append (“IsVisible:” +t.IsVisible+ “\n”);

            sb.Append (“IsByRef (pass by reference):” +t.IsByRef+ “\n”);

            Console.WriteLine(sb.ToString ());

        }

        public static void AssemblyExplore()

        {

            StringBuilder sb = new StringBuilder();

            Assembly asm = Assembly.Load(“Demo”);

            sb.Append(“FullName: ” + asm.FullName + “\n”);

            sb.Append(“Location(path): ” + asm.Location + “\n”);

            Type[] types = asm.GetTypes();

            foreach (Type t in types)

            {

                sb.Append(” Type: ” + t + “\n”);

            }

            Console.WriteLine(sb.ToString());

        }

        static void Main(string[] args)

        {

            AssemblyExplore();

            Console.ReadKey();

            Type t = typeof(Demo.DemoClass);

            TypeExplore2(t);

            Console.ReadKey();

            MemberExplore3(typeof(Demo.DemoClass));

            Console.ReadKey();

             FieldExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

             PropertyExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

             MethodExplore(typeof(Demo.DemoClass));

            Console.ReadKey();

        }

    }

}

NOTE

  • “MethodAttribute” owns a set of bit flags that indactes some proproties of the method  such as “Abstract”, “Static”, “Virtual”,”Public”, “Private”, and so on.
  •  Methods can have parameters and returned values. Class MethodInfo provides a “GetParameters()” method to get an array of parameter objects. The method related parameters are all encapsulated in the “ParameterInfo” type.

EX.

using System;

using System.Reflection;

Class ListMembers

{

     public void Main()

     {

        Type t = typeof(String);

        Console.WriteLine(“Listing all the public constructors of the {0} type”, t);

        ‘ Constructors.

        ConstructorInfo[] ci = t.GetConstructors((BindingFlags.Public || BindingFlags.Instance))

        Console.WriteLine(“//Constructors”);

        PrintMembers(ci);

      }

      public void PrintMembers(MemberInfo[] ms)

      {

          MemberInfo m;

          foreach( m in ms)

              Console.WriteLine(“{0}{1}”, ”     “, m);

          Console.WriteLine();

      }

}

EX.

using System;

using System.IO;

using System.Reflection;

 Class Mymemberinfo

{

    Public void Main()

    {

        Console.WriteLine (“\nReflection.MemberInfo”);

        ‘ Gets the Type and MemberInfo.

        Type MyType = Type.GetType(“System.IO.File”);

        Type[] Mymemberinfoarray = MyType.GetMembers();

        ‘ Gets and displays the DeclaringType method.

        Console.WriteLine(“\nThere are {0} members in {1}.”,

            Mymemberinfoarray.Length, MyType.FullName);

        Console.WriteLine(“{0}.”, MyType.FullName);

        If (MyType.IsPublic)

            Console.WriteLine(“{0} is public.”, MyType.FullName);

    }

}

EX.

using System ;

using System.Reflection;

 Class MyMethodInfo

{

    Public void Main()

        Console.WriteLine(“Reflection.MethodInfo”);

        ‘ Gets and displays the Type.

        Type MyType= Type.GetType(“System.Reflection.FieldInfo”);

        ‘ Specifies the member for which you want type information.

        MethodInfo Mymethodinfo = MyType.GetMethod(“GetValue”);

        Console.WriteLine((MyType.FullName & “.” & Mymethodinfo.Name));

        ‘ Gets and displays the MemberType property.

        MemberInfo Mymembertypes = Mymethodinfo.MemberType;

        if (MemberTypes.Constructor = Mymembertypes )

            Console.WriteLine(“MemberType is of type All”);

        elseIf(MemberTypes.Custom = Mymembertypes)

            Console.WriteLine(“MemberType is of type Custom”);

        elseIf (MemberTypes.Event = Mymembertypes)

            Console.WriteLine(“MemberType is of type Event”);

        elseIf ( MemberTypes.Field = Mymembertypes)

            Console.WriteLine(“MemberType is of type Field”);

        elseIf (MemberTypes.Method = Mymembertypes)

            Console.WriteLine(“MemberType is of type Method”);

        elseIf (MemberTypes.Property = Mymembertypes)

            Console.WriteLine(“MemberType is of type Property”);

        elseIf (MemberTypes.TypeInfo = Mymembertypes)

            Console.WriteLine(“MemberType is of type TypeInfo”);

       }

  }

}

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace ReflectionProject5

{

     public class MyObject

    {

        //public fields

        public string myStringField;

        public int myIntField;

        public MyObject myObjectField;

         //public properties

        public string MyStringProperty { get; set; }

        public int MyIntProperty { get; set; }

        public MyObject MyObjectProperty { get; set; }

         //public events

        public event EventHandler MyEvent1;

        public event EventHandler MyEvent2;

    }

    class Program

    {

        static void Main(string[] args)

        {

            Type myObjectType = typeof(MyObject);

             System.Reflection.FieldInfo[] fieldInfo = myObjectType.GetFields();

             foreach (System.Reflection.FieldInfo info in fieldInfo)

            {

                Console.WriteLine(info.Name);

            }

            Console.ReadKey();

         }

    }

}

Reflection-Attribute Programming

Suppose we have a messaging system, in this system, there exists a method  called “SendMsg”, used to send a short message to seomone:

EX.

//Title: title; author: the writer; content: msg content; receiverId: Recipient Id

public bool SendMsg(string title, string author, string content, int receiverId)

{

            //Do sending action…

}

we soon find having so many parameters listed inside the method would lead to terrible extensibility. Therefore, we’d better define a Message class to encapsulate the short message and then pass a Message object ot the method:

EX.

public class Message

{

            private string title;

            private string author;

            private string content;

            private int receiverId;

            //…omitted

}

public bool SendMsg (Messag msg)

{

// Do sending action…

}

NOTE

To implement any changes to this method once the application is deployed, the application is required to be re-compiled or achieve the changes through a method overloading. Another way of achieving the changes on the method is by implementing “Attributes” that can be loaded to an object.

Attibute is an object that can be loaded into the assembly and objects in the assembly. These objects include the assembly itsefl, modules, classes, interfaces, strcutures, constructors, methods and parameters, etc. The object annotated with attribut(s) is called the target of the attribute(s).

Attribute provides a mechanism to add metadata (data describing data), through which we can provide instruction to the compiler or provide a description of the data.

EX.

The above problem can be solved by using the “ObsoleteAttribute” attribute. We can decorate the old SendMsg() method with the above “ObsoleteAttribute” attribute to tell the compiler that this method is outdated and later where there are methods marked with the Obselete attribute i the program the compiler will give a related warning:

 using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace RefelectionAttribute

{

    public class Message { }

   public class TestClass

   {

      //add the Obsolete attribute

      [Obsolete(“Please use the new SendMsg(Message msg) overriden method”)]

      public static void ShowMsg()

      {

        Console.WriteLine(“This is the old SendMsg() method”);

      }

      public static void ShowMsg(Message msg)

      {

         Console.WriteLine(“The new SendMsg() method”);

      }

   }

    class Program

    {

        static void Main(string[] args)

        {

            TestClass.ShowMsg();

            TestClass.ShowMsg(new Message());

            Console.ReadKey();

        }

   }

}

Writing Custom Attributes

Supose we have a common demand, when we create or update a class file, we’d better provide such description of when this class is and who creates it. Int he past, we used to achive that by implementing the following:

 //Update: Matthew, 2010-2-10, modified ToString () method

//Update: Li, 2010-1-18

//Created: Zhang Yi, 2010-1-15

public class DemoClass

{

  //Class body…

}

This indeed can help to achieve the above target, but what if one day we want to save these records to the database for the backup of it? we know that attributes can be used to add metadata to specified types, with which to describe the types to achieve that, the following are the steps to create an attribute class:

1- Create a class that encapsulates the following metadata:

public  class RecordAttribute

{

            private string recordType; //Record Type: Update/create

            private string author; // the writer

            private DateTime date; // Update/creation date

            private string memo; // Remarks

            public RecordAttribute (string recordType, string author, string date)

        {

                        this.recordType = recordType;

                        this.author = author;

                        this.date = Convert.ToDateTime(date);

            }

            // For the positional parameters, usually only get accessor

            public string RecordType {get {return recordType;}}

            public string Author {get {return author;}}

            public DateTime Date {get {return date;}}

            public string Memo

            {

                        get {return memo;}

                        set {memo = value;}

            }

}

NOTE

  • Based on the .Net requirements, the date in the constructor parameter must be a constant, Type type, or a constant arrary, we can not directly pass in the DateTime type.
  • There is no difference between this class and a normal class. .NET will not identify it an Attribute because of the suffix Attribute. So how could it become an Attribute and applied to a class? To implement the custom RecordAttribute attribute, the body of the class needs no changes, and what we only need to do is to make it inherit from the Attribute base class, and use the AttributeUsage attribute:

 EX.

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]

public class RecordAttribute: Attribute

{

   //omitted…

}

The AttributeUsage attribute is used to describe the usage of the attributes. It is used to specify what type or object it identified attributes can be applied to. AttributeTargets corresponds to a set of bit flags, which defines the types and objects that related attribute can be applied to:

EX.

 [Flags]

public enum AttributeTargets

{

   Assembly = 1, // properties can be applied to the assembly.

   Module = 2, // attributes can be applied to the module.

   Class = 4, / / can be applied to the class.

   Struct = 8, // can be applied to the structure.

   Enum = 16, // can be applied to the enumeration.

   Constructor = 32, // can be applied to the constructor.

   Method = 64, // can be applied to method.

   Property = 128, // can be applied to attribute.

   Field = 256, // can be applied to the field.

   Event = 512, // can be applied to the event.

   Interface = 1024, // can be applied on the interface.

   Parameter = 2048, // can be applied to the parameters.

   Delegate = 4096, // can be applied to the Delegate.

   ReturnValue = 8192, // can be applied to return value.

   GenericParameter = 16384, // can be applied to the generic parameters.

   All = 32767, // applied to any properties.

}

The AttributeUsage corresponds to a set of bit flags, and as such we can use the bitwise OR “|” to combine each fit flag:

EX.

 [AttributeUsage (AttributeTargets.Class | AttributeTargets.Interface)

 The above means that this attribute not only can be applied to class, but be applied to interface.

 The AllowMultiple property us used to specify whether the attribute can be repeatedly applied to a yoe (The default is false). Once the custom attribute is created, it is time to use it, and use the refelection to view the custom attribute information as follows:

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

namespace CustomAttributeDemoNS

{

   [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = false)]

   public class RecordAttribute : Attribute

   {

      private string recordType; //Record Type: Update/create

      private string author; // the writer

      private DateTime date; // Update/creation date

      private string memo; // Remarks

      public RecordAttribute(string recordType, string author, string date)

     {

        this.recordType = recordType;

        this.author = author;

        this.date = Convert.ToDateTime(date);

     }

        // For the positional parameters, usually only get accessor

        public string RecordType { get { return recordType; } }

        public string Author { get { return author; } }

        public DateTime Date { get { return date; } }

         public string Memo

        {

             get { return memo; }

             set { memo = value; }

         }

    }

    [Record(“update”, “Matthew”, “2010-1-20”, Memo = “modify the ToString() method”)]

    [Record(“update”, “Jimmy”, “2010-1-18”)]

    [Record(“create”, “Zhang Yi”, “2010-1-15”)]

     public class DemoClass

    {

        public override string ToString()

        {

            return “This is a demo class”;

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            DemoClass demo = new DemoClass();

            Console.WriteLine(demo.ToString());

            Console.ReadLine();

             //Use Reflection to view the Custom Attribute

            Type t = typeof(DemoClass);

            Console.WriteLine(“{0} The following list applies to the RecordAttribute attribute:”, t);

            //Get all the RecordAttributes features

            object[] records = t.GetCustomAttributes(typeof(RecordAttribute), false);

            foreach (RecordAttribute record in records)

            {

                Console.WriteLine(“{0}”, record);

                Console.WriteLine(“Type: {0}”, record.RecordType);

                Console.WriteLine(“of:{0}”, record.Author);

                Console.WriteLine(“Date:{0}”, record.Date.ToShortDateString());

                if (!String.IsNullOrEmpty(record.Memo))

                {

                    Console.WriteLine(“Note:{0}”, record.Memo);

                }

          }

            Console.ReadKey();

        }

    }

}

Dynamic Creating of Objects

EX.

public class Calculator

{

            private int x;

            private int y;

            public Calculator ()

        {

                        x = 0;

                        y = 0;

            }

        public Calculator(int x, int y)

       {

                        this.x = x;

                        this.y = y;

            }

}

To create refelection to objects with non-argument constructor, you can use “CreateInstance” method of the Assembly:

Assembly asm = Assembly.GetExecutingAssembly();

Object obj = asm.CreateInstance(“Reflection4.Calculator”,true);

Where

  • The first parameter of the CreateInstance method respresents the string name of type instance to create.
  • The second parameter indicates whether the string name is case sensitive or not.
  • The CreateInstance method returns an Object, which means if you want to use this object you need to make a type conversion.

 Another way to create objects is to call the static method “CreateInstance” of the activator class:

ObjectHandle handler = Activator.CreateInstance(null, “Reflection4.Calculator”);

Object obj = handler.Unwrap();

Where

  • The first argument of the “CreateInstance” method represnets the name of the assembly (null means the current assembly).
  • The second parameter corresponds to the type name you want to create.
  • The “Activator.CreateInstance” method returns an object of ObjectHandle, which has to make an “Unwrap()” invocation to return object type.
  • The “ObjectHandle” is included in the “Ssytem.Runtime.emoting” namespace, which is relevant to the Remoting operation.

 Create Reflection Objects Using Constructors with Parameters

To create refelection objects via constructor having arguments, we can use the overloaded “CreateInstance()” method of Assembly:

EX.

// create an object using constructor with parameters

Assembly asm = Assembly.GetExecutingAssembly();

Object[] parameters = new Object[2]; //define the constructor required parameters

parameters[0] = 3;

parameters[1] = 5;

Object obj = asm.CreateInstance (“Reflection4.Calculator”, true, BindingFlags.Default, null, parameters, null, null);

Where

  • The first parameter of the CreateInstance method respresents the string name of type instance to create.
  • The second parameter indicates whether the string name is case sensitive or not.
  • The “BindingFlags” is used for restrict the search for members of the type, and “Default” is its default value.
  • The “Binder” which encapsulates the rules that the “CreateInstance” method uses to bind objects. We almost always pass null.
  • The “parameters” is an Object[] array type, which contains the parameters that we pass in. Constructor with parameters willuse them.
  • The last two parameters is a “CultureInfo” type, which contains information about the language and culture.

 Dynamically Invoke Methods

We dynamically inoke mthods by using the .Net refelection approach via two ways:

 1- Call the “InvoleMember” method of the Type object, passin in the object you want to call the methods, as well as Specifying “BindingFlags” as “InvokeMethod”, and according to the method signature, you may also need to pass associated parameters.

2- First obtain the method object to call throug the “GetMethod” method to the “Type” object, then call the “Invoke” method on the method object, and according to the method signature, you may also need to pass parameters.

 

NOTE

The use of “InvokeMember” is not limited to call the object’s method, and it can also be used to obtain the object’s fields, properties, etc.

Call methods using InvokeMember/MethodInfo.Invoke

EX.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Reflection;

using System.Runtime.Remoting;

namespace RefelectionProject5

{

     public class Calculator

    {

        private int x;

        private int y;

         public Calculator()

        {

            x = 0;

            y = 0;

        }

        public Calculator(int x, int y)

        {

            this.x = x;

            this.y = y;

        }

        public int Add()

        {

            int total = 0;

            total = x + y;

            Console.WriteLine(“Invoke Instance Method:”);

            Console.WriteLine(String.Format (“[Add]: {0} plus {1} equals to {2}”, x, y, total));

            return total;

        }

        public static void Add(int x, int y)

        {

            int total = x + y;

            Console.WriteLine (“Invoke Static Method:”);

            Console.WriteLine (String.Format (“[Add]: {0} plus {1} equals to {2}”, x, y, total));

        }

    }

    class Program

    {

        static void Main(string[] args)

        {

            //First way of creating an object Reflection

            //Assembly asm = Assembly.GetExecutingAssembly();

            //Object obj = asm.CreateInstance(“ReflectionProject5.Calculator”, true);

             //Another way to create object Reflection is to call the static method CreateInstance of the Activator class

            //ObjectHandle handler = Activator.CreateInstance(null, “ReflectionProject5.Calculator”);

            //Object obj = handler.Unwrap();

             // create an object using constructor with parameters

            Assembly asm = Assembly.GetExecutingAssembly();

            Object[] parameters = new Object[2]; //define the constructor required parameters

            parameters[0] = 3;

            parameters[1] = 5;

            Object obj = asm.CreateInstance(“ReflectionProject5.Calculator”, true, BindingFlags.Default, null, parameters, null, null);

             //Calling methods using InvokeMember

            Type t = typeof(Calculator);

             //Calling instant Method

            int result1 = (int)t.InvokeMember(“Add”, BindingFlags.InvokeMethod, null, obj, null);

            Console.WriteLine(String.Format(“The result is {0}”, result1));

             ////Calling Static Method

            Object[] parameters2 = new Object[2];

            parameters2[0] = 6;

            parameters2[1] = 9;

             int result2 = (int)t.InvokeMember(“Add”, BindingFlags.InvokeMethod, null, typeof(Calculator), parameters2);

            Console.WriteLine(String.Format(“The result is {0}”, result2));

             //Call method using MethodInfo.Invoke

            MethodInfo mi = t.GetMethod(“Add”, BindingFlags.Instance | BindingFlags.Public);

                mi.Invoke(obj, null);

                Console.WriteLine(String.Format(“The result is {0}”, mi));

             //Call static method using MethodInfo.Invoke

            MethodInfo mi = t.GetMethod(“Add”, BindingFlags.Static | BindingFlags.Public);

               mi.Invoke(null, parameters2);

            //can also be: Mi.Invoke(t, parameters2);

         }

    }

}

EX.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
namespace reflection
{
    public partial class Form1 : Form
    {
        public Form1()
        {            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            int n = 45;
            //string n = “vineet”;
            System.Type t = n.GetType();
            MessageBox.Show(t.ToString());//Display type of varible
            MessageBox.Show(t.Name);//Display name of variable
            MessageBox.Show(t.Namespace);//Display namespace by name
            MessageBox.Show(t.IsArray.ToString());//Display boolean value
            MessageBox.Show(t.IsClass.ToString());//Display boolean value
            MessageBox.Show(t.Module.ToString());//Display module(library) of assembly
            MessageBox.Show(t.MemberType.ToString());//Display membertype by name
            MessageBox.Show(t.GetProperties().ToString());//Display property by name
            MessageBox.Show(t.GetType().ToString());//Display type defined in assembly
            MessageBox.Show(t.GetMethods().ToString());//Display method by name
            MessageBox.Show(t.GetInterfaces().ToString());//Display interface by name
            MessageBox.Show(t.FullName.ToString());//Display type of variable by name
            MessageBox.Show(t.BaseType.ToString());//Display base type
            MessageBox.Show(t.Attributes.ToString());//Display attribute by name
            MessageBox.Show(t.Assembly.ToString());//Display assembly by name
            MessageBox.Show(t.AssemblyQualifiedName.ToString());//Display AssemblyQualifiedName
            System.Reflection.Assembly o = System.Reflection.Assembly.Load(“mscorlib.dll”);
            MessageBox.Show(o.GetName().ToString());//Display information about  mscorlib assembly
            object obj = o.GetType();
            MessageBox.Show(obj.ToString());//Display name of runtime assembly
            ConstructorInfo[] ci = t.GetConstructors();//Display information about constructors
            foreach (ConstructorInfo i in ci)
            {
                MessageBox.Show(i.ToString());
            }
            MethodInfo[] mi = t.GetMethods();//Display information about methods
            foreach (MethodInfo i in mi)
            {
                MessageBox.Show(i.ToString());
            }
            PropertyInfo[] pi = t.GetProperties();//Display information about properties
            foreach (PropertyInfo i in pi)
            {
                MessageBox.Show(i.ToString());
            }
            MemberInfo[] mf = t.GetMembers();//Display information about members
            foreach (MemberInfo i in mf)
            {
                MessageBox.Show(i.ToString());
            }
            EventInfo[] ei = t.GetEvents();//Display information about events
            foreach (EventInfo i in ei)
            {
                MessageBox.Show(i.ToString());
            }
            FieldInfo[] fi= t.GetFields();//Display information about fields
            foreach (FieldInfo i in fi)
            {
                MessageBox.Show(i.ToString());
            }
        }
    }
}

Conclusion

In general Reflection is a process by C# and VB.Net in .Net environment where we can get the details information about specific assembly (i.e. methods, constructors, attributes, properties, modules, global classes, parameters, and many more at run time. Reflection can also modify the structure and the behavior of a computer programs.

 Finally, reflection is a mechanism by which we can get metadata information from an assembly at run time. Reflection is used for data binding in .Net Framework, and it is also used for testing in .Net Framework. There are System.Reflection is the namespace for the reflection. System.Reflection namespace defines the assembly module, MemberInfo, PropertyInfo, MethodInfo, ConstuctorInfo, FieldInfo, EventInfo etc. The System.Type is the base class for Reflection. Ssytem.Type find the type name, namespace, module type etc. System.Type is also an abstract class.

References

Zhu, X. (2010) C# 4.0 Reflection Programming – Part I [Online]. Available from: http://dotnetslackers.com/articles/csharp/C-Sharp-4-0-Reflection-Programming-Part1.aspx (Accessed: 15 October 2013).

Zhu, X.(2010) C# 4.0 Reflection Programming- Part 2 [Online]. Available from: http://dotnetslackers.com/articles/csharp/C-Sharp-4-0-Reflection-Programming-Part2.aspx (Accessed: 15 October 2013).

Zhu, X. (2010) C# 4.0 Reflection Programming – Part 3 [Online]. Available from: http://dotnetslackers.com/articles/csharp/C-Sharp-4-0-Reflection-Programming-Part3.aspx  (Accessed: 15 October 2013).

Zhu, X. (2010) C# 4.0 Reflection Programming – Part 4 [Online]. Available from: http://dotnetslackers.com/articles/csharp/C-Sharp-4-0-Reflection-Programming-Part4.aspx  (Accessed: 15 October 2013).

 Esangbedo, I. (2007) Reflection in C# Tutorial [Online]. Available from: http://www.codeproject.com/Articles/17269/Reflection-in-C-Tutorial (Accessed: 15 October 2013).

C# Programming (n.d.) C#- Reflection [Online]. Available from: http://www.tutorialspoint.com/csharp/csharp_reflection.htm (Accessed: 15 October 2013).

Cannaday, B. (2008) C# Tutorial – Using Reflection to Get Object Information [Online]. Available from: http://tech.pro/tutorial/841/csharp-tutorial-using-reflection-to-get-object-information (Accessed: 15 October 2013).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: