从构造函数创建委托

Hap*_*mad 5 c# reflection expression-trees .net-4.5

使用反射,我试图从无参数构造函数创建一个委托,如下所示:

Delegate del = GetMethodInfo( () => System.Activator.CreateInstance( type ) ).CreateDelegate( delType );

static MethodInfo GetMethodInfo( Expression<Func<object>> func )
{
    return ((MethodCallExpression)func.Body).Method;
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了这个例外:"无法绑定到目标方法,因为它的签名或安全透明性与委托类型的不兼容." 什么会奏效?

请注意,自上一版本的.NET以来,至少为此配置文件移动了CreateDelegate.现在它在MethodInfo上.

Pet*_*hie 11

正如phoog指出的那样,构造函数不会"返回"一个值; 加上你得到的信息ConstructorInfo与否MethodInfo; 这意味着你不能直接在它周围创建一个委托.您必须创建调用构造函数并返回值的代码.例如:

var ctor = type.GetConstructor(Type.EmptyTypes);
if (ctor == null) throw new MissingMethodException("There is no constructor without defined parameters for this object");
DynamicMethod dynamic = new DynamicMethod(string.Empty,
            type,
            Type.EmptyTypes,
            type);
ILGenerator il = dynamic.GetILGenerator();

il.DeclareLocal(type);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);

var func = (Func<object>)dynamic.CreateDelegate(typeof(Func<object>));
Run Code Online (Sandbox Code Playgroud)

当然,如果您在编译时不知道类型,那么您只能处理Object...


Анд*_*NOP 6

尝试一下:

Dictionary<Type, Delegate> cache = new Dictionary<Type, Delegate>();
public T Create<T>()
{
    if (!cache.TryGetValue(typeof(T), out var d))
        d = cache[typeof(T)]
            = Expression.Lambda<Func<T>>(
                Expression.New(typeof(T)),
                Array.Empty<ParameterExpression>())
            .Compile();
    return ((Func<T>)d)();
}
Run Code Online (Sandbox Code Playgroud)

反射很慢!速度测试在这里(俄语):https : //ru.stackoverflow.com/a/860921/218063

  • 谢谢!这帮助了我。如果您也需要参数,请确保将新调用参数传递给 Lambda 调用。给定 ConstructorInfo,这是我的 TResult 构造函数的代码,该构造函数采用单个 T 参数: 'NewExpression newExpression = Expression.New(constructorInfo, Expression.Parameter(typeof(T))); Func&lt;T, TResult&gt; constructorFunc = Expression.Lambda&lt;Func&lt;T, TResult&gt;&gt;(newExpression, newExpression.Arguments.Cast&lt;ParameterExpression&gt;().ToArray()).Compile();' (2认同)