Activator.CreateInstance 性能替代方案

问题描述 投票:0回答:4

我正在使用 RedGate 进行一些性能评估。 我注意到使用

Activator.CreateInstance
(带有两个构造函数参数)动态创建实例需要相当长的时间...是否有更好的替代方案仍然使用反射方法(不是显式实例化)?

c# .net performance reflection
4个回答

20
投票

不要忘记DynamicMethod

这是如何通过默认构造函数创建新实例的示例

public static ObjectActivator CreateCtor(Type type)
{
    if (type == null)
    {
        throw new NullReferenceException("type");
    }
    ConstructorInfo emptyConstructor = type.GetConstructor(Type.EmptyTypes);
    var dynamicMethod = new DynamicMethod("CreateInstance", type, Type.EmptyTypes, true);
    ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
    ilGenerator.Emit(OpCodes.Nop);
    ilGenerator.Emit(OpCodes.Newobj, emptyConstructor);
    ilGenerator.Emit(OpCodes.Ret);
    return (ObjectActivator)dynamicMethod.CreateDelegate(typeof(ObjectActivator));
}

public delegate object ObjectActivator();

这里有更多关于性能比较

的信息

测量 InvokeMember...1.5643784 秒内迭代 1000000 次。

测量 MethodInfo.Invoke...0.8150111 秒内 1000000 次迭代。

测量 DynamicMethod...0.0330202 秒内迭代 1000000 次。

测量直接调用...0.0136752 秒内 1000000 次迭代。


9
投票

我创建了一个解决方案,可以用作

Activator.CreateInstance
的替代品。你可以在我的博客上找到它。

示例:

var myInstance = InstanceFactory.CreateInstance(typeof(MyClass));
var myArray1 = InstanceFactory.CreateInstance(typeof(int[]), 1024);
var myArray2 = InstanceFactory.CreateInstance(typeof(int[]), new object[] { 1024 });

代码:

public static class InstanceFactory
{
  private delegate object CreateDelegate(Type type, object arg1, object arg2, object arg3);

  private static ConcurrentDictionary<Tuple<Type, Type, Type, Type>, CreateDelegate> cachedFuncs = new ConcurrentDictionary<Tuple<Type, Type, Type, Type>, CreateDelegate>();

  public static object CreateInstance(Type type)
  {
    return InstanceFactoryGeneric<TypeToIgnore, TypeToIgnore, TypeToIgnore>.CreateInstance(type, null, null, null);
  }

  public static object CreateInstance<TArg1>(Type type, TArg1 arg1)
  {
    return InstanceFactoryGeneric<TArg1, TypeToIgnore, TypeToIgnore>.CreateInstance(type, arg1, null, null);
  }

  public static object CreateInstance<TArg1, TArg2>(Type type, TArg1 arg1, TArg2 arg2)
  {
    return InstanceFactoryGeneric<TArg1, TArg2, TypeToIgnore>.CreateInstance(type, arg1, arg2, null);
  }

  public static object CreateInstance<TArg1, TArg2, TArg3>(Type type, TArg1 arg1, TArg2 arg2, TArg3 arg3)
  {
    return InstanceFactoryGeneric<TArg1, TArg2, TArg3>.CreateInstance(type, arg1, arg2, arg3);
  }

  public static object CreateInstance(Type type, params object[] args)
  {
    if (args == null)
      return CreateInstance(type);

    if (args.Length > 3 || 
      (args.Length > 0 && args[0] == null) ||
      (args.Length > 1 && args[1] == null) ||
      (args.Length > 2 && args[2] == null))
    {
        return Activator.CreateInstance(type, args);   
    }

    var arg0 = args.Length > 0 ? args[0] : null;
    var arg1 = args.Length > 1 ? args[1] : null;
    var arg2 = args.Length > 2 ? args[2] : null;

    var key = Tuple.Create(
      type,
      arg0?.GetType() ?? typeof(TypeToIgnore),
      arg1?.GetType() ?? typeof(TypeToIgnore),
      arg2?.GetType() ?? typeof(TypeToIgnore));

    if (cachedFuncs.TryGetValue(key, out CreateDelegate func))
      return func(type, arg0, arg1, arg2);
    else
      return CacheFunc(key)(type, arg0, arg1, arg2);
  }

  private static CreateDelegate CacheFunc(Tuple<Type, Type, Type, Type> key)
  {
    var types = new Type[] { key.Item1, key.Item2, key.Item3, key.Item4 };
    var method = typeof(InstanceFactory).GetMethods()
                                        .Where(m => m.Name == "CreateInstance")
                                        .Where(m => m.GetParameters().Count() == 4).Single();
    var generic = method.MakeGenericMethod(new Type[] { key.Item2, key.Item3, key.Item4 });

    var paramExpr = new List<ParameterExpression>();
    paramExpr.Add(Expression.Parameter(typeof(Type)));
    for (int i = 0; i < 3; i++)
      paramExpr.Add(Expression.Parameter(typeof(object)));

    var callParamExpr = new List<Expression>();
    callParamExpr.Add(paramExpr[0]);
    for (int i = 1; i < 4; i++)
      callParamExpr.Add(Expression.Convert(paramExpr[i], types[i]));

    var callExpr = Expression.Call(generic, callParamExpr);
    var lambdaExpr = Expression.Lambda<CreateDelegate>(callExpr, paramExpr);
    var func = lambdaExpr.Compile();
    cachedFuncs.TryAdd(key, func);
    return func;
  }
}

public static class InstanceFactoryGeneric<TArg1, TArg2, TArg3>
{
  private static ConcurrentDictionary<Type, Func<TArg1, TArg2, TArg3, object>> cachedFuncs = new ConcurrentDictionary<Type, Func<TArg1, TArg2, TArg3, object>>();

  public static object CreateInstance(Type type, TArg1 arg1, TArg2 arg2, TArg3 arg3)
  {
    if (cachedFuncs.TryGetValue(type, out Func<TArg1, TArg2, TArg3, object> func))
      return func(arg1, arg2, arg3);
    else
      return CacheFunc(type, arg1, arg2, arg3)(arg1, arg2, arg3);
  }

  private static Func<TArg1, TArg2, TArg3, object> CacheFunc(Type type, TArg1 arg1, TArg2 arg2, TArg3 arg3)
  {
    var constructorTypes = new List<Type>();
    if (typeof(TArg1) != typeof(TypeToIgnore))
      constructorTypes.Add(typeof(TArg1));
    if (typeof(TArg2) != typeof(TypeToIgnore))
      constructorTypes.Add(typeof(TArg2));
    if (typeof(TArg3) != typeof(TypeToIgnore))
      constructorTypes.Add(typeof(TArg3));

    var parameters = new List<ParameterExpression>()
    {
      Expression.Parameter(typeof(TArg1)),
      Expression.Parameter(typeof(TArg2)),
      Expression.Parameter(typeof(TArg3)),
    };

    var constructor = type.GetConstructor(constructorTypes.ToArray());
    var constructorParameters = parameters.Take(constructorTypes.Count).ToList();
    var newExpr = Expression.New(constructor, constructorParameters);
    var lambdaExpr = Expression.Lambda<Func<TArg1, TArg2, TArg3, object>>(newExpr, parameters);
    var func = lambdaExpr.Compile();
    cachedFuncs.TryAdd(type, func);
    return func;
  }
}

public class TypeToIgnore
{
}

1
投票

如果您正在寻找一组涵盖 1-16 个参数的预定义方法,那么您可以:

using System;
using System.Linq.Expressions;
using System.Reflection;

namespace YournamespaceHere;

public class Constructors<TKnownType>
{
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15), typeof(T16) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var t12 = Expression.Parameter(typeof(T12), "t12");
        var t13 = Expression.Parameter(typeof(T13), "t13");
        var t14 = Expression.Parameter(typeof(T14), "t14");
        var t15 = Expression.Parameter(typeof(T15), "t15");
        var t16 = Expression.Parameter(typeof(T16), "t16");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14), typeof(T15) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var t12 = Expression.Parameter(typeof(T12), "t12");
        var t13 = Expression.Parameter(typeof(T13), "t13");
        var t14 = Expression.Parameter(typeof(T14), "t14");
        var t15 = Expression.Parameter(typeof(T15), "t15");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13), typeof(T14) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var t12 = Expression.Parameter(typeof(T12), "t12");
        var t13 = Expression.Parameter(typeof(T13), "t13");
        var t14 = Expression.Parameter(typeof(T14), "t14");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12), typeof(T13) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var t12 = Expression.Parameter(typeof(T12), "t12");
        var t13 = Expression.Parameter(typeof(T13), "t13");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11), typeof(T12) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var t12 = Expression.Parameter(typeof(T12), "t12");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10), typeof(T11) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var t11 = Expression.Parameter(typeof(T11), "t11");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9), typeof(T10) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var t10 = Expression.Parameter(typeof(T10), "t10");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8, T9>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8), typeof(T9) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var t9 = Expression.Parameter(typeof(T9), "t9");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8, t9);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8, t9).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, T8, TKnownType> New<T1, T2, T3, T4, T5, T6, T7, T8>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7), typeof(T8) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var t8 = Expression.Parameter(typeof(T8), "t8");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7, t8);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, T8, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7, t8).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, T7, TKnownType> New<T1, T2, T3, T4, T5, T6, T7>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6), typeof(T7) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var t7 = Expression.Parameter(typeof(T7), "t7");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6, t7);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, T7, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6, t7).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, T6, TKnownType> New<T1, T2, T3, T4, T5, T6>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5), typeof(T6) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var t6 = Expression.Parameter(typeof(T6), "t6");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5, t6);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, T6, TKnownType>>(newExpression, t1, t2, t3, t4, t5, t6).Compile();
    }
    public static Func<T1, T2, T3, T4, T5, TKnownType> New<T1, T2, T3, T4, T5>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var t5 = Expression.Parameter(typeof(T5), "t5");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4, t5);
        return Expression.Lambda<Func<T1, T2, T3, T4, T5, TKnownType>>(newExpression, t1, t2, t3, t4, t5).Compile();
    }
    public static Func<T1, T2, T3, T4, TKnownType> New<T1, T2, T3, T4>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var t4 = Expression.Parameter(typeof(T4), "t4");
        var newExpression = Expression.New(ctor, t1, t2, t3, t4);
        return Expression.Lambda<Func<T1, T2, T3, T4, TKnownType>>(newExpression, t1, t2, t3, t4).Compile();
    }
    public static Func<T1, T2, T3, TKnownType> New<T1, T2, T3>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2), typeof(T3) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var t3 = Expression.Parameter(typeof(T3), "t3");
        var newExpression = Expression.New(ctor, t1, t2, t3);
        return Expression.Lambda<Func<T1, T2, T3, TKnownType>>(newExpression, t1, t2, t3).Compile();
    }
    public static Func<T1, T2, TKnownType> New<T1, T2>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1), typeof(T2) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var t2 = Expression.Parameter(typeof(T2), "t2");
        var newExpression = Expression.New(ctor, t1, t2);
        return Expression.Lambda<Func<T1, T2, TKnownType>>(newExpression, t1, t2).Compile();
    }
    public static Func<T1, TKnownType> New<T1>(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, new Type[] { typeof(T1) }, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var t1 = Expression.Parameter(typeof(T1), "t1");
        var newExpression = Expression.New(ctor, t1);
        return Expression.Lambda<Func<T1, TKnownType>>(newExpression, t1).Compile();
    }
    public static Func<TKnownType> New(Type t, BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance)
    {
        if (t == null) throw new ArgumentNullException(nameof(t));
        if (!typeof(TKnownType).IsAssignableFrom(t)) throw new ArgumentException($"{nameof(TKnownType)} cannot be assigned to from the type provided by {nameof(t)}.", nameof(t));
        var ctor = t.GetConstructor(bindingFlags, Type.DefaultBinder, Type.EmptyTypes, null);
        if (ctor == null)
            throw new ArgumentException(null, nameof(t));
        var newExpression = Expression.New(ctor);
        return Expression.Lambda<Func<TKnownType>>(newExpression).Compile();
    }
}

我没有包含具有不同 ref/out 语义的所有 16 个参数的定义,因为这将是 316+315...+31 方法 委托。加起来超过 6000 万个方法/委托。 😅 我相信您可以使用这篇文章中的详细信息来制作您自己的。

编辑: 我忘了提到,如果您想提供需要创建超出默认 .ctor (

new
约束)的特定类型类型参数的库,这会特别有用。

© www.soinside.com 2019 - 2024. All rights reserved.