Erstellen Sie einen Delegaten aus dem Konstruktor

.net-4.5 c# expression-trees reflection

Frage

Mit Reflection versuche ich, einen Delegaten aus einem parameterlosen Konstruktor wie folgt zu erstellen:

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

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

Aber ich bekomme diese Ausnahme: "Kann nicht an die Zielmethode binden, weil seine Signatur oder Sicherheitstransparenz nicht mit der des Delegattyps kompatibel ist." Was wird funktionieren?

Beachten Sie, dass CreateDelegate für dieses Profil seit der vorherigen Version von .NET verschoben wurde. Jetzt ist es auf MethodInfo.

Akzeptierte Antwort

Wie phoog zeigt, gibt ein Konstruktor keinen Wert zurück. Außerdem erhalten Sie Informationen darüber mit ConstructorInfo und nicht MethodInfo ; Das bedeutet, dass Sie nicht direkt einen Delegierten dafür erstellen können. Sie müssen Code erstellen, der den Konstruktor aufruft und den Wert zurückgibt. Beispielsweise:

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

Wenn Sie den Typ zur Kompilierzeit nicht kennen, können Sie natürlich nur mit dem Object ...


Beliebte Antwort

Es wäre nicht sehr nützlich, einen Delegaten zu haben, der auf einen Konstruktor verweist, da Konstruktoren keinen Rückgabewert haben. Der Delegat würde ein Objekt konstruieren, aber keine Möglichkeit, einen Verweis darauf zu behalten.

Sie können natürlich Delegaten erstellen, die das neu konstruierte Objekt zurückgeben:

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

Sie können auch einen Delegaten über die Invoke() Methode des ConstructorInfo des ConstructorInfo erstellen

Für andere Arten von Objekten:

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

Die letzte Zeile geht davon aus, dass es einen barrierefreien parameterlosen Konstruktor gibt.

Update mit 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);
}


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow