Reflection
The dictionary meaning of the word ‘Reflection’ is ‘to look back to itself’. This is exactly what is meant by the term reflection in programming world. Reflection is an ability of application to look into the structure of itself. Using the reflection technology, we can retrieve the information about the contents of an assembly (constituting classes and interfaces).Similarly we can drill down to get the members of these types like fields, methods, and properties. Not only this, but we can also instantiate these types and invoke the methods on these. We can even prepare, compile, and load assemblies at runtime.
Another advantage of Reflection is it allows you to load assemblies on the fly and treat them as if they were part of your application.Typically this can be used to extend your application after it is released to customers.
For instance we use this feature to add additional reports to customers other than the standard reports that ship with the application, with out having to alter any base app code and with out having to perform any patches. Each of our report file is a .net class, the standard reports are compiled with in the Main assembly and if the customer requests for different sets of reports, we write those class files compile them to an assembly and drop in our app bin folder. Thatz all we need to do, the reflection code in the app will take care of the rest.
To demonstrate this, let's setup a hypothetical situation in which we have an application, and a .NET DLL unreferenced by our application whose types we need to access at runtime. The DLL will be called MyDLL.dll, and the application will be called MyApp.exe. How would we view the types contained inside MyDLL from MyApp at runtime when MyDLL isn't referenced by MyApp? The
System.Runtime.Assembly
class can be used to access MyDLL in the following manner:System.Reflection.Assembly myDllAssembly = System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
The
myDllAssembly
object can now be used to access the types contained inside MyDLL. To access a type contained inside MyDLL, System.Reflection.Assembly
possesses a method called GetType()
, which can return a System.Type
that can be used to access all the members of the type we want to retrieve from inside MyDLL. Note that the System.Reflection.Assembly.GetType()
method is not to be confused with the GetType()
method possessed by all objects; they are related, but quite different, and we will discuss the other GetType()
method later. Back to our example; let's say, there is a type inside MyDLL called MyDLLForm
which inherits from System.Windows.Forms.Form
and is contained in the namespace MyDLLNamespace
. To obtain the System.Type
of this, we could do the following:System.Reflection.Assembly myDllAssembly = System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
System.Type MyDLLFormType = myDllAssembly.GetType("MyDLLNamespace.MyDLLForm");
MyDLLFormType
now holds the System.Type
of MyDLLForm
. We can now access all the members and contained types inside MyDLLForm
from MyDLLFormType
. However, using this GetType()
method will not create an instance of MyDLLForm
. To access a type contained inside MyDLL
and create an instance of it, System.Reflection.Assembly
possesses another method called CreateInstance()
. Say, we wanted to create an instance of MyDLLForm
, we could use something like this:System.Reflection.Assembly myDllAssembly = System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
Form MyDLLFormInstance = (Form)myDllAssembly.CreateInstance("MyDLLNamespace.MyDLLForm");
MyDLLFormInstance
now holds an instance of MyDLLForm
(remember that MyDLLForm
inherits from Form
). To create an instance of MyDLLForm
, that method will invoke MyDLLForm
's constructor. By way of that overload, CreateInstance
is expecting a constructor that takes no arguments, as we only passed it the type name we want to create an instance of. However, let's say there is a constructor we want to use to create an instance of MyDLLForm
that takes two arguments, a string
and an int
. To do that, and for example, to pass it a string of "Hi" and an integer value of 113 (one of my favorite numbers), we could use this:System.Reflection.Assembly myDllAssembly =
System.Reflection.Assembly.LoadFile("%MyDLLPath%\\MyDLL.dll");
//the arguments we will pass
object[] argstopass = new object[] { (object)"Hi", (object)113 };
Form MyDLLFormInstance = (Form)myDllAssembly.CreateInstance("MyDLLNamespace.MyDLLForm",
false, //do not ignore the case
BindingFlags.CreateInstance, //specifies we want to call a ctor method
null, //a null binder specifies the default binder will be used (works in most cases)
argstopass, //the arguments (based on the arguments,
//CreateInstance() will decide which ctor to invoke)
null, //CultureInfo is null so we will use
//the culture info from the current thread
null //no activation attributes
);
No comments:
Post a Comment