Everybody
knows that Reflection is a really very important topic in .NET. So I
won't repeat the importance of it, it is an unquestionable subject;
besides, I have to admit that it saved my life too many times.
But like every good thing Reflection has also some disadvantages, too.
One of the important disadvantages of the Reflection is performance.
Actually, if we talk about considering a few reflection operations,
there won't be any performance problem because Reflection is not slow.
It is just slower than the other ways which make us do the same
operations. For example:
//
WAY 1 normal instance creation
ArrayList list = new
ArrayList();
// WAY 2 Using reflection to create an instance of a
type
ArrayList list = (ArrayList)typeof(ArrayList).GetConstructor(Type.EmptyTypes).Invoke(null);
|
If we call the methods above not too many times at the same time, there
won't be any performance problem but there might be a performance
problem if we call this reflection example too many times in any
iteration as for, while, foreach etc. For example:
Stopwatch watch = new
Stopwatch();
Type t = typeof(ArrayList);
ConstructorInfo info = t.GetConstructor(Type.EmptyTypes);
object o = null;
ArrayList list = null;
watch.Start();
for (int i =
0; i < 1000000; i++)
{
list = new ArrayList();
}
watch.Stop();
Console.WriteLine(string.Format("new : {0} ms", watch.ElapsedMilliseconds));
GC.Collect();
o = null;
watch.Start();
for (int i =
0; i < 1000000; i++)
{
o = info.Invoke(null);
}
watch.Stop();
Console.WriteLine(string.Format("Reflection : {0} ms",
watch.ElapsedMilliseconds)); |
When you run the code above, the output will be as follows:
new : 23 ms
Reflection : 1131 ms
As you see in the previous example, if you use Reflection to create too
many items, it will work very slowly. To we talk about the first method
(using new), we can only use it when we know the object's Type during
the coding time. Otherwise, we cannot use the new keyword to create an
instance of an unknown type. In the world of programming, this is a very
common situation because we usually don't know the actual type during
the coding, so we have to use Reflection in scenarios like this to
create instances of a Type.
There are two different ways to make this code run faster. One of them
is using
Activator class to create object instances
from Types. If we want to use the Activator class in the example above
to create an instance of an object, the code will be as runs:
o = null;
watch.Start();
for (int i =
0; i < 1000000; i++)
{
o = Activator.CreateInstance(t);
}
watch.Stop();
Console.WriteLine(string.Format("Activator : {0} ms",
watch.ElapsedMilliseconds)); |
If we execute this code, we'll get the following result:
Activator : 207 ms.
However, this is not the best way. Yes, this is fast but there is also
another way which run faster than the Activator class.
The last method I mention is using DynamicMethod
method. Dynamic method is a method which we instantiate in the runtime
in memory, and works as any method we wrote in our programs
/// <summary>
/// Class
which creates a dynamic method for the given type
/// </summary>
public class
ObjectCreateMethod
{
delegate object
MethodInvoker();
MethodInvoker
methodHandler = null;
public ObjectCreateMethod(Type type)
{
CreateMethod(type.GetConstructor(Type.EmptyTypes));
}
public ObjectCreateMethod(ConstructorInfo target)
{
CreateMethod(target);
}
void CreateMethod(ConstructorInfo target)
{
DynamicMethod
dynamic = new DynamicMethod(string.Empty,
typeof(object),
new Type[0],
target.DeclaringType);
ILGenerator il =
dynamic.GetILGenerator();
il.DeclareLocal(target.DeclaringType);
il.Emit(OpCodes.Newobj, target);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
methodHandler = (MethodInvoker)dynamic.CreateDelegate(typeof(MethodInvoker));
}
public object CreateInstance()
{
return methodHandler();
}
}
ObjectCreateMethod
inv = new ObjectCreateMethod(info);
o = null;
watch.Start();
for (int i = 0; i < 1000000; i++)
{
o = inv.CreateInstance();
}
watch.Stop();
Console.WriteLine(string.Format("Method Invocation : {0} ms",
watch.ElapsedMilliseconds));
|
When we run the code above, the output will be as follows:
Method Invocation : 27 ms.
Here in this example, we are creating an instance of DynamicMethod and
fill DynamicMethod's body by using
ILGenerator class.
And in the IL, we use the
Newobj-(Argument: Method
Token)- OpCode (which means creating an instance of a Type) to create an
instance, and than we return the created object to the caller. This is
also what the
new keyword does in the IL. So our
performance will be as the same as the new keyword's performance. Also
to use the DynamicMethod, we used CreateDelegate method of the
DynamicMethod, which creates a new delegate which we can use to execute
this method. By calling
CreateInstance method in the
ObjectCreateMethod
class, our DynamicMethod is invoked and returns the result.
Finally as you see here, if you use DynamicMethod to create instances of
a Type (if you don't know the exact type during coding, otherwise you
can use
new :) ) is the fastest way to create an
instance of the object.
You don't need to write your own Dynamic method creator classes, you can
use the ObjectCreateMethod instances in your applications. Of course
this method is just for the constructors which has no parameters. If you
want to run a constructor which takes parameters, then you have to
write your own Dynamic Methods.
See you later ...
Download
Test Codes -
More
about Dynamic Methods