How to pass ctor args in Activator.CreateInstance or use IL?

后端 未结 8 1742
野的像风
野的像风 2020-12-07 16:06

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. (

8条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-07 16:35

    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! :->

提交回复
热议问题