使用Delegate调用构造函数

我发现了这个,但试图使用它并失败了。

如何使用reflection创建对象并通过将其置于委托中来加快速度?

DynamicMethod dm = new DynamicMethod("MyCtor", t, new Type[] { }); var ctor = t.GetConstructor(new Type[] { }); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit(OpCodes.Ldarg_0); ilgen.Emit(OpCodes.Newobj, ctor); ilgen.Emit(OpCodes.Ret); var d = (Func)dm.CreateDelegate(t); dm.Invoke(null, new object[] { }); 

在把它删除之前我试图至少调用它,当我在上面做的时候我得到了错误

 An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll 

附加信息:调用目标抛出了exception。

如果我调用d()而不是我得到exception

 An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll Additional information: Type must derive from Delegate. 

如何将一个无参数构造函数放入委托并调用它?

如果您可以访问.NET 3.5(使用Func建议),您可能会发现ExpressionILGenerator更容易:

 class Foo { } static void Main() { Func func = GetCtor(); // cache this somewhere! Foo foo = func(); } static Func GetCtor() { Type type = typeof(T); Expression body = Expression.New(type); return Expression.Lambda>(body).Compile(); } 

很容易扩展它以使用特定的构造函数,传递参数或添加post-constructor属性绑定; 演员,转换等(见相关答案 )。 如果你有一个特定的场景,我会很乐意添加一个例子。

另请注意,您应该缓存并重新使用任何此类构造函数 – 否则您将失去优势(即不要重新创建每次调用的委托)。

试试这个 –

 Action myCtor = CreateCtor(t, Type.EmptyTypes, typeof(Action)); public static Delegate CreateCtor(Type type, Type[] parameterTypes, Type delegateType, string typeParameterName) { var ctorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null); if (ctorInfo == null) { string parameterString = string.Empty; if(parameterTypes.Length > 0) { string[] parameterStrings = new string[parameterTypes.Length]; for(int i = 0; i < parameterTypes.Length; ++i) { parameterStrings[i] = parameterTypes[i].ToString(); } parameterString = string.Join(",", parameterStrings); } throw new ArgumentException(string.Format("Type '{0}' does not define .ctor({1}).", type, parameterString), typeParameterName); } bool isVisible = type.IsVisible && (ctorInfo.IsPublic && !ctorInfo.IsFamilyOrAssembly); DynamicMethod dynamicCtor = new DynamicMethod(Guid.NewGuid().ToString("N"), type, parameterTypes, ctorInfo.Module, !isVisible); var il = dynamicCtor.GetILGenerator(); for (int i = 0; i < parameterTypes.Length; ++i) { switch (i) { case 0: il.Emit(OpCodes.Ldarg_0); break; case 1: il.Emit(OpCodes.Ldarg_1); break; case 2: il.Emit(OpCodes.Ldarg_2); break; case 3: il.Emit(OpCodes.Ldarg_3); break; default: il.Emit(OpCodes.Ldarg, i); break; } } il.Emit(OpCodes.Newobj, ctorInfo); il.Emit(OpCodes.Ret); return dynamicCtor.CreateDelegate(delegateType); } 

构造函数没有参数,所以你不应该在堆栈上加载参数ilgen.Emit(OpCodes.Ldarg_0)

 class Program { static void Main() { var t = typeof(Program); var dm = new DynamicMethod("MyCtor", t, new Type[0], t.Module); var ctor = t.GetConstructor(new Type[0]); ILGenerator ilgen = dm.GetILGenerator(); ilgen.Emit(OpCodes.Newobj, ctor); ilgen.Emit(OpCodes.Ret); var del = (Func)dm.CreateDelegate(typeof(Func)); var instance = del(); Console.WriteLine(instance); } } 

构造委托的通用方法,直接调用构造函数。 使用给定委托类型的签名自动搜索给定类型的构造函数,并构造该类型的委托。 代码在这里:

 ///  /// Reflective object construction helper. /// All methods are thread safe. ///  public static class Constructor { ///  /// Searches an instanceType constructor with delegateType-matching signature and constructs delegate of delegateType creating new instance of instanceType. /// Instance is casted to delegateTypes's return type. /// Delegate's return type must be assignable from instanceType. ///  /// Type of delegate, with constructor-corresponding signature to be constructed. /// Type of instance to be constructed. /// Delegate of delegateType wich constructs instance of instanceType by calling corresponding instanceType constructor. public static Delegate Compile(Type delegateType,Type instanceType) { if (!typeof(Delegate).IsAssignableFrom(delegateType)) { throw new ArgumentException(String.Format("{0} is not a Delegate type.",delegateType.FullName),"delegateType"); } var invoke = delegateType.GetMethod("Invoke"); var parameterTypes = invoke.GetParameters().Select(pi => pi.ParameterType).ToArray(); var resultType = invoke.ReturnType; if(!resultType.IsAssignableFrom(instanceType)) { throw new ArgumentException(String.Format("Delegate's return type ({0}) is not assignable from {1}.",resultType.FullName,instanceType.FullName)); } var ctor = instanceType.GetConstructor( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null); if(ctor == null) { throw new ArgumentException("Can't find constructor with delegate's signature","instanceType"); } var parapeters = parameterTypes.Select(Expression.Parameter).ToArray(); var newExpression = Expression.Lambda(delegateType, Expression.Convert(Expression.New(ctor, parapeters), resultType), parapeters); var @delegate = newExpression.Compile(); return @delegate; } public static TDelegate Compile(Type instanceType) { return (TDelegate) (object) Compile(typeof (TDelegate), instanceType); } } 

是Yappi项目资源的一部分。 使用它,您可以构造委托调用给定类型的任何构造函数,包括带参数的构造函数(ref和out参数除外)。

样品用法:

 var newList = Constructor.Compile>>(typeof (List)); var list = newList(100); 

在构造委托之后,将其存储在静态字典中或具有generics参数的类的静态字段中。 不要每次都构造新的委托。 使用一个委托构造给定类型的多个实例。