8

リフレクションを使用して、次のようなパラメーターなしのコンストラクターからデリゲートを作成しようとしています。

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

static MethodInfo GetMethodInfo( Expression<Func<object>> func )
{
    return ((MethodCallExpression)func.Body).Method;
}

しかし、この例外が発生します。「ターゲットメソッドの署名またはセキュリティの透過性がデリゲートタイプのそれと互換性がないため、ターゲットメソッドにバインドできません。」何が機能しますか?

少なくともこのプロファイルでは、以前のバージョンの.NET以降、CreateDelegateが移動されたことに注意してください。今ではMethodInfoにあります。

4

3 に答える 3

14

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>));

もちろん、コンパイル時にタイプがわからない場合は、処理することしかできませんObject...

于 2012-05-15T03:32:21.273 に答える
7

それを試してみてください:

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)();
}

反射がとても遅いです!速度テストはここにあります(ロシア語):https ://ru.stackoverflow.com/a/860921/218063

于 2018-07-27T06:57:23.183 に答える
3

コンストラクターには戻り値がないため、コンストラクターを指すデリゲートがあるとあまり役に立ちません。デリゲートはオブジェクトを作成しますが、オブジェクトへの参照を保持する方法はありません。

もちろん、新しく構築されたオブジェクトを返すデリゲートを作成することもできます。

Func<object> theDelegate = () => new object();

Invoke()コンストラクターのメソッドからデリゲートを作成することもできますConstructorInfo

他のタイプのオブジェクトの場合:

Func<string> theDelegate = () => new string('w', 3);
Func<SomeClassInMyProject> theDelegate = () => new SomeClassInMyProject();

最後の行は、アクセス可能なパラメーターなしのコンストラクターがあることを前提としています。

で更新CreateDelegate()

T CallConstructor<T>() where T : new() { return new T(); }
Delegate MakeTheDelegate(Type t)
{
    MethodInfo generic = //use your favorite technique to get the MethodInfo for the CallConstructor method
    MethodInfo constructed = generic.MakeGenericMethod(t);
    Type delType = typeof(Func<>).MakeGenericType(t);
    return constructed.CreateDelegate(delType);
}
于 2012-05-15T03:24:40.987 に答える