CreateDelegate mit unbekannten Typen
Ich versuche zu erstellen, Delegieren, zum Lesen/schreiben von Eigenschaften der unbekannten Art von Klassen zur Laufzeit.
Habe ich eine generische Klasse Main<T>
und eine Methode, die wie folgt aussieht:
Delegate.CreateDelegate(typeof(Func<T, object>), get)
wo get
ist ein MethodInfo
von der Eigenschaft, die gelesen werden sollen. Das problem ist, dass, wenn die Eigenschaft gibt int
(ich glaube, das passiert für value-Typen) der obige code wirft ArgumentException, weil die Methode nicht gebunden werden kann. Bei string funktioniert es auch.
Das problem zu lösen, änderte ich den code, so dass entsprechende Delegate-Typ wird erzeugt, indem mit MakeGenericType
. So jetzt der code:
Type func = typeof(Func<,>);
Type generic = func.MakeGenericType(typeof(T), get.ReturnType);
var result = Delegate.CreateDelegate(generic, get)
Das problem ist jetzt, dass der erzeugte Delegat-Instanz generic
so, ich habe mit DynamicInvoke
die so langsam als Reine Reflexion zu Lesen das Feld.
Also meine Frage ist warum ist, dass der erste code-snippet schlägt mit Wert-Typen. Nach MSDN es sollte funktionieren, da es sagt, dass
Den Rückgabetyp eines Delegaten ist kompatibel mit dem Rückgabetyp einer Methode, wenn der Rückgabetyp der Methode ist restriktiver als der Rückgabetyp des Delegaten
und so führen die Delegierten in den zweiten Ausschnitt so, dass es schneller ist als Reflexion.
Dank.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist ein Weg, um Ihr problem zu lösen. Erstellen Sie eine generische Methode:
Diese Weise, C#, compiler kümmert sich um das einfügen der notwendigen Boxen (falls vorhanden) zu konvertieren
f(t)
(TypU
) zuobject
. Jetzt können Sie Reflexion nennen dieseMakeDelegate
Methode mitU
eingestellt@get.ReturnType
, und was Sie wieder werden einFunc<T, object>
die aufgerufen werden können, ohne Rückgriff auf mitDynamicInvoke
.Ihre original-code funktioniert nur für Referenz-Typen. Das ist, warum string kein problem war, es leitet sich direkt aus dem System.Objekt. Dass Sie einen Wert-Typ leitet sich von ValueType und Objekt ist eine schöne illusion auf dem Papier, sondern tatsächlich erfordert code. Der C# - compiler automatisch aussendet, dass der code, es erfordert eine boxing-Konvertierung. Das ist der Teil, der fehlt hier, es gibt keine Laufzeit-Konvertierung von int nach object ohne die FELD opcode.
Können Sie bekommen, dass der Befehl in deinem code, aber Sie müssen System.Reflexion.Aussenden.
Bevor Sie dorthin gehen, überprüfen Sie zuerst, ob das, was du jetzt hast ist eigentlich zu langsam. Die Kosten der Reflexion ist das Graben der Metadaten aus der Versammlung. Das war getan, wenn Sie erstellt die Delegierten, die Typ-info-Cache nach, dass.
Sie Aufruf schlägt fehl, da Sie erfordern Objekt keine Wert-Typ (wie INT) -- offensichtlich
Func<T, int>
ist nicht einFunc<T, Int>
- es funktioniert nicht mit jedem vt wie double oder bool. Kehren Sie entweder eine Box Int (vt oder was auch immer Du hast) . oder (vielleicht besser) verwenden Sie reflektion, Strahlen-API.Mittels Reflexion emittieren Klassen, die Sie erstellen eine dynamische Methoden und speichern Sie Sie als Delegierte oder erstellen Sie Dynamische Delegierten und speichern Sie Sie in einigen Ihrer Struktur. Könnten Sie dies nur einmal tun (vielleicht einmal pro Laufzeit) speichern Sie es in einigen Dict und rufen, wenn nötig.
hoffe, es hilft.
Lukas
Ist es möglich für Sie zu beschränken, die generische Methode nur mit Referenz-Typen und weiteres erstellen, nur mit Wert-Typen und entscheiden, welche Funktionen zu verwenden, entsprechend?