First of all, Activator.CreateInstance() is a right way.
But, there is a more interesting way that is:
- 10 times faster
- Don't wrap exceptions in TargetInvocationException
Just create expression that calls constructor:
public static Func<object[], object> CreateConstructorDelegate(ConstructorInfo method) { var args = Expression.Parameter(typeof(object[]), "args"); var parameters = new List<Expression>(); var methodParameters = method.GetParameters().ToList(); for (var i = 0; i < methodParameters.Count; i++) { parameters.Add(Expression.Convert( Expression.ArrayIndex(args, Expression.Constant(i)), methodParameters[i].ParameterType)); } var call = Expression.Convert(Expression.New(method, parameters), typeof(object)); Expression body = call; var callExpression = Expression.Lambda<Func<object[], object>>(body, args); var result = callExpression.Compile(); return result; }
Performance test:
public void activator() { var stopwatch = new Stopwatch(); const int times = 10000000; stopwatch.Start(); for (int i = 0; i < times; i++) { var v = Activator.CreateInstance(typeof (C)); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms with activator"); var del = CreateConstructorDelegate(typeof(C).GetConstructor(new Type[0])); stopwatch = new Stopwatch(); stopwatch.Start(); var args = new object[0]; for (int i = 0; i < times; i++) { var v = del(args); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms with expression"); }
Output:
1569ms with activator 134ms with expression
But:
- C# 3.0 only
- Complile() is long running operation
Just for curious.