我找到this但尝试使用它并失败了。
如何使用反射创建对象并通过将其置于委托中来加快速度?
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<T>)dm.CreateDelegate(t);
dm.Invoke(null, new object[] { });
在把它删除之前我试图至少调用它,当我在上面做的时候我得到了错误
An unhandled exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll
附加信息:调用目标引发了异常。
如果我调用d()而不是我得到异常
An unhandled exception of type 'System.ArgumentException' occurred in mscorlib.dll
Additional information: Type must derive from Delegate.
如何将一个无参数构造函数放入委托并调用它?
答案 0 :(得分:11)
如果您可以访问.NET 3.5(使用Func<T>
建议),您可能会发现Expression
比ILGenerator
更容易:
class Foo { }
static void Main() {
Func<Foo> func = GetCtor<Foo>(); // cache this somewhere!
Foo foo = func();
}
static Func<T> GetCtor<T>() {
Type type = typeof(T);
Expression body = Expression.New(type);
return Expression.Lambda<Func<T>>(body).Compile();
}
很容易扩展它以使用特定的构造函数,传递参数或添加post-constructor属性绑定;演员,转换等(见this related answer)。如果您有特定的场景,我很乐意添加一个示例。
另请注意,您应该缓存并重新使用任何此类构造函数 - 否则您将失去优势(即不要重新创建每次调用的委托)。
答案 1 :(得分:4)
试试这个 -
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);
}
答案 2 :(得分:0)
构造函数没有参数,所以你不应该在堆栈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<Program>)dm.CreateDelegate(typeof(Func<Program>));
var instance = del();
Console.WriteLine(instance);
}
}
答案 3 :(得分:0)
构造委托的通用方法,直接调用构造函数。 使用给定委托类型的签名自动搜索给定类型的构造函数,并构造该类型的委托。代码在这里:
/// <summary>
/// Reflective object construction helper.
/// All methods are thread safe.
/// </summary>
public static class Constructor
{
/// <summary>
/// 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.
/// </summary>
/// <param name="delegateType">Type of delegate, with constructor-corresponding signature to be constructed.</param>
/// <param name="instanceType">Type of instance to be constructed.</param>
/// <returns>Delegate of delegateType wich constructs instance of instanceType by calling corresponding instanceType constructor.</returns>
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<TDelegate>(Type instanceType)
{
return (TDelegate) (object) Compile(typeof (TDelegate), instanceType);
}
}
是Yappi项目来源的一部分。使用它,您可以构造委托调用给定类型的任何构造函数,包括带参数的构造函数(ref和out参数除外)。
样本用法:
var newList = Constructor.Compile<Func<int, IList<String>>>(typeof (List<String>));
var list = newList(100);
构建委托后,将其存储在静态字典中或使用泛型参数的类的静态字段中。不要每次都构造新的委托。使用一个委托来构造给定类型的多个实例。