I need a performance enhanced Activator.CreateInstance() and came across this article by Miron Abramson that uses a factory to create the instance in IL and then cache it. (
I wrote this a while ago. It's using the .NET 3.5 Linq Expression trees rather than emitting IL, which is almost as fast, and more maintainable. It can take up to 4 constructor arguments.
Using any constructor arguments like you want to do might be a bit slower however due to looking up the constructor based on the argument types, but it's still much faster than with reflection. Also with IL emission there would have to be some lookup I think.
You have to specify the exact type which you want to construct as it's no IOC/DI container. Maybe you can extend and adapt it to your needs.
// usage:
Cat myCat = Instantiator.New("furry", /* isCute*/ true);
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
static public class Instantiator
{
static Instantiator()
{
Debug.Assert(typeof(TInstance).IsValueType || (typeof(TInstance).IsClass && !typeof(TInstance).IsAbstract),
String.Concat("The type ", typeof(TInstance).Name, " is not constructable."));
}
static public TInstance New()
{
return InstantiatorImpl.CtorFunc();
}
static public TInstance New(TA valueA)
{
return InstantiatorImpl.CtorFunc(valueA);
}
static public TInstance New(TA valueA, TB valueB)
{
return InstantiatorImpl.CtorFunc(valueA, valueB);
}
static public TInstance New(TA valueA, TB valueB, TC valueC)
{
return InstantiatorImpl.CtorFunc(valueA, valueB, valueC);
}
static public TInstance New(TA valueA, TB valueB, TC valueC, TD valueD)
{
return InstantiatorImpl.CtorFunc(valueA, valueB, valueC, valueD);
}
static private Expression CreateLambdaExpression(params Type[] argTypes)
{
Debug.Assert(argTypes != null);
ParameterExpression[] paramExpressions = new ParameterExpression[argTypes.Length];
for (int i = 0; i < paramExpressions.Length; i++)
{
paramExpressions[i] = Expression.Parameter(argTypes[i], String.Concat("arg", i));
}
ConstructorInfo ctorInfo = typeof(TInstance).GetConstructor(argTypes);
if (ctorInfo == null)
{
throw new ArgumentException(String.Concat("The type ", typeof(TInstance).Name, " has no constructor with the argument type(s) ", String.Join(", ", argTypes.Select(t => t.Name).ToArray()), "."),
"argTypes");
}
return Expression.Lambda(Expression.New(ctorInfo, paramExpressions), paramExpressions);
}
static private class InstantiatorImpl
{
static public readonly Func CtorFunc = Expression.Lambda>(Expression.New(typeof(TInstance))).Compile();
}
static private class InstantiatorImpl
{
static public readonly Func CtorFunc = Instantiator.CreateLambdaExpression>(typeof(TA)).Compile();
}
static private class InstantiatorImpl
{
static public readonly Func CtorFunc = Instantiator.CreateLambdaExpression>(typeof(TA), typeof(TB)).Compile();
}
static private class InstantiatorImpl
{
static public readonly Func CtorFunc = Instantiator.CreateLambdaExpression>(typeof(TA), typeof(TB), typeof(TC)).Compile();
}
static private class InstantiatorImpl
{
static public readonly Func CtorFunc = Instantiator.CreateLambdaExpression>(typeof(TA), typeof(TB), typeof(TC), typeof(TD)).Compile();
}
}
Have teh funz with it! :->