Wie können Sie eine Variable vom Typ 'object' explizit in eine generische Mehrfacheinschränkung umwandeln?

8

Wir haben eine generische Erweiterungsmethode, die nur für Objekte funktioniert, die sowohl die INotifyCollectionChanged- als auch die IEnumerable-Schnittstelle unterstützen. Es ist so geschrieben:

%Vor%

Das folgende kompiliert gut, da ObservableCollection<string> beide Schnittstellen implementiert und dank des Schlüsselworts 'var' ist typedType stark typisiert:

%Vor%

Wir versuchen dies jedoch von einem ValueConverter aus aufzurufen. Das Problem ist, dass der eingehende Wert vom Typ object ist und obwohl wir testen können, dass das übergebene Objekt beide Schnittstellen implementiert, können wir nicht herausfinden, wie wir es explizit umwandeln können, damit wir diese generische Erweiterungsmethode aufrufen können. Dies funktioniert nicht (offensichtlich) ...

%Vor%

Wie können Sie also ein Objekt auf mehrere Interfaces umwandeln, damit Sie das generische Objekt aufrufen können? Nicht einmal sicher, dass es möglich ist.

    
MarqueIV 11.05.2015, 22:26
quelle

2 Antworten

2

Der sauberste Weg, den ich mir vorstellen kann, wäre dynamic . Da Erweiterungsmethoden jedoch nicht mit dynamic (siehe bleich) funktionieren, müssen Sie explizit auf die Erweiterungsmethode verweisen.

%Vor%

BEARBEITEN Als Hinweis auf die Frage, auf die ich hier hingewiesen habe, ist zu beachten, dass der Aufruf der Methode mit explizitem dyanmic als Typargument (über DoSomething<dynamic> ) nicht Arbeit - es verursacht Kompilierungsfehler, wenn versucht wird, mit mehreren Einschränkungen übereinzustimmen. Wenn nicht mehrere Integritätsbedingungen verwendet werden, führt dies dazu, dass dynamic basierend auf dem Kompilierungszeittyp der übergebenen Variablen, nicht dem Laufzeittyp aufgelöst wird.

Dies führt zu einem Aufruf von Extensions.UnknownType<dynamic> , dessen dynamic zur Laufzeit aufgelöst wird - was bedeutet, dass der vollständig abgeleitete Typ des angegebenen Parameters verwendet wird. Solange dieser Parameter die gewünschten Schnittstellen implementiert, gehen Sie los.

Seien Sie vorsichtig, da es wie bei dynamic code zu Problemen kommen kann, die erst zur Laufzeit erkannt werden. Verwenden Sie sparsam!

Wenn Sie mehrere Aufrufe mit denselben generischen Parametern durchführen, sollten Sie eine generische Hilfsmethode in Ihrem Konverter hinzufügen und dann das mit value as dynamic

aufrufen

Zusatz :

Bei der Verwendung von dynamic versucht alles, was gegen das Objekt dynamic aufgerufen wird, zur Laufzeit als Element des angegebenen Typs aufgelöst zu werden. nicht sucht nach Erweiterungsmethoden, da sie inhärent existieren in einer ganz anderen Klasse, oft eine andere Versammlung.

    
David 11.05.2015, 22:33
quelle
0

Sie können versuchen, mithilfe von MethodInfo und delegates einen Delegaten für die richtige Methode abzurufen.

Die folgende Lösung verwendet nicht dynamic , sondern ein wenig Reflection . Grundsätzlich führt die Methode die folgenden Operationen durch:

  1. Ruft einen Delegaten der Methode ab, die Sie aufrufen möchten, aber für einen anderen, bekannten Typ.
  2. Ruft die generische Methodendefinition ab.
  3. Ruft dann die Methode MethodInfo für den Objekttyp ab.
  4. Ruft die Erweiterungsmethode durch Aufrufen der letzten MethodInfo .
  5. auf

Die _Placeholder -Klasse ist der bekannte Typ, der zum Abrufen des anfänglichen Delegaten verwendet wird, Sie können jedoch jeden anderen Typ verwenden, der die generischen Einschränkungen erfüllt.

Auf diese Weise haben Sie auch die Möglichkeit, den Namen der Erweiterungsmethode und ihre Einschränkungen zu überprüfen.

Ein guter Ansatz würde auch das endgültige MethodInfo (oder Delegate) zwischenspeichern, um zu vermeiden, teure Anrufe zu wiederholen.

%Vor%     
Rubidium 37 14.05.2015 15:12
quelle

Tags und Links