2010-12-02 3 views
6

ich mit ESRI ArcObjects COM-Bibliothek arbeite, versuche ich wirklich hart, welche Art sein sollte, um herauszufinden, „ausgewählt“:Herausfinden, welche Schnittstellen für ein COM-Objekt abfragbar sind?

IMxDocument doc = m_application.Document as IMxDocument; 
object selected = doc.SelectedItem; 

SelectedItem gibt einen ComObject (nicht Null), in der Regel den Datentyp darstellt, ist Zurzeit ausgewählt. Allerdings habe ich nicht die geringste Ahnung, auf welchen Typ ich es werfen soll. Wenn ich es debuggen, ich sehe nicht wirklich etwas Nützliches:

http://imgur.com/Yfo6G

(Uhr Debug nachdem der Wert eingestellt ist)

ArcObjects Bibliothek ESRI ist riesig, und ziemlich schlecht dokumentiert ist, ich einfach kann es nicht herausfinden. Ich ging sogar so weit, manuell etwa 50 Schnittstellen zu testen, von denen ich dachte, dass sie es sein sollten.

Hat jemand irgendwelche Ideen, wie ich das herausfinden kann?

EDIT Um ihre Dokumentation zu klären ist absolut keine Hilfe, noch ist ihre Foren.

Antwort

5

Nachdem Sie Ihre Frage, die Antworten und die Kommentare gelesen haben, müssen Sie möglicherweise ein Dienstprogramm schreiben, um die Antwort mit roher Gewalt zu finden.

Verwenden Sie Reflektion, um eine Liste von Schnittstellen aus Ihrer Interop-Assembly zu entfernen, und führen Sie dann einfach eine Schleife über diese Liste, um festzustellen, ob Ihr Objekt die einzelnen Schnittstellen unterstützt.

aktualisieren

Einige Beispielcode:

object unknown = //your com object... 

    Type someComObjectType = typeof(ExampleTypeInInteropAssembly); 

    Assembly interopAssembly = someComObjectType.Assembly; 

    Func<Type, bool> implementsInterface = iface => 
    { 
     try 
     { 
      Marshal.GetComInterfaceForObject(unknown, iface); 
      return true; 
     } 
     catch (InvalidCastException) 
     { 
      return false; 
     } 
    }; 

    List<Type> supportedInterfaces = interopAssembly. 
     GetTypes(). 
     Where(t => t.IsInterface). 
     Where(implementsInterface). 
     ToList(); 

    if (supportedInterfaces.Count > 0) 
    { 
     supportedInterfaces.ForEach(Console.WriteLine); 
    } 
    else 
    { 
     Console.WriteLine("No supported interfaces found :("); 
    } 
+0

Ich glaube nicht, dass 'IsAssignableFrom' in diesem Fall funktioniert. –

+0

@Nicolas Sind Sie sicher? –

+0

In Ihrem Code wird 'unknown.GetType() 'immer' System .__ ComObject 'zurückliefern, da es sich um den .net verwalteten Wrapper um' IUnknown' handelt. Also, von einem '.net type System' Punkt der vue, implementiert System .__ ComObject wirklich keine der com Schnittstellen, an denen wir interessiert sind. –

0

versuchen Sie selected.GetType(). ToString();

Es sollte den Typ des Objekts geben, das es ist.

+1

"System .__ ComObject" Ich bekomme diese. – UberJumper

0

Versuchen Sie, die Dokumentation zu lesen. Wenn das SDK nicht hilft, versuchen Sie, die Typbibliothek in dem OLEView-Dienstprogramm zu lesen, das mit Windows Resource Kit und Visual C++ geliefert wird.

0

Ich bin affraid es keine Möglichkeit, die Schnittstellen durch ein COM-Objekt implementiert aufzulisten ist. Sie können jedoch nach wie vor Brute-Force- es, indem sie es mit einer Liste der Schnittstelle abfragt Sie interessiert sind

Edit:.

Einige Code, die helfen können:

foreach(Type comInterfacType in comInterfaceTypesIAmInterestedIn) { 
    IntPtr comInterface = Marshal.GetComInterfaceForObject(o, comInterfaceType); 
    if(comInterface != IntPtr.Zero) { 
    Console.WriteLine("o implements " + comInterfaceType); 
    Marshal.ReleaseComObject(o); 
    } 
} 
0

(würde habe dies als Kommentar hinzugefügt, aber ich bin ein Noob und mein Rep ist nicht ausreichend)

Es ist eine Weile her, seit ich mit ArcObjects gearbeitet habe, aber ich erinnere mich, dass das Objekt m Odel war lächerlich groß und schlecht dokumentiert. Nichtsdestotrotz bezieht sich IMxDocument.SelectedItem nicht auf das Element, das im TOC/Layer-Steuerelement ausgewählt ist? Wenn ja, würde es nicht eine Instanz von IMap oder ILayer zurückgeben?

+0

Das war, was ich erwarten würde. Aber darauf hat uns ESRI hingewiesen. Wir wissen, dass "etwas" in ausgewählten Objekten gespeichert wird. Wenn wir eine leere Karte machen, keine Ebenen. Nichts ausgewählt == null, wähle ein Werkzeug == etwas. – UberJumper

7

Ich bin nicht vertraut mit dieser Bibliothek, aber ich kann einige Vorschläge machen.Wenn Sie das Problem aus der Sicht von COM betrachten, werden Sie feststellen, dass es keine einfache Antwort gibt.

(Denken Sie daran, dass in COM alle Objekte nur Objekte sind, und dass die einzige Voraussetzung ist, dass sie IUNKNOWN (und möglicherweise andere Schnittstellen) unterstützen muss. Also die Antwort auf die Frage, um was für ein Objekt es sich handelt "kann oft mehr als eine Antwort haben."

Die wichtige Sache zu erinnern ist, dass in COM die Liste der Schnittstellen für ein Objekt in keiner Art von Metadaten wie in .NET definiert ist (außer dass eine Bibliothek in der Regel bietet eine optionale Typ Bibliothek als eine Form der Dokumentation für Entwicklungswerkzeuge - mehr dazu in einer Minute).

Die Liste der Schnittstellen wird offiziell nur durch die Ergebnisse der Aufruf von IUNKNOWN's QueryInterface() - Methode definiert - das heißt, sie wird ausschließlich durch das Ergebnis der Codeausführung definiert.

Manchmal ist die Liste möglicherweise hart codiert. Häufig ist die Liste möglicherweise erst zur Laufzeit bekannt, und es ist möglicherweise nicht einmal bekannt, bis jemand fragt. Die einzige Regel ist, dass die Liste der Schnittstellen stabil sein muss und was ich vernünftige aufrufen: die Liste kann nicht im Laufe der Zeit für eine bestimmte Objektinstanz ändern; Es muss IUNKNOWN unterstützen, was manchmal vergessen wird; Wenn es eine abgeleitete Schnittstelle unterstützt, muss es seine Basis unterstützen; und ein paar andere bin ich sicher, dass ich es vergesse.

Dieser letzte Punkt ist entscheidend für Ihr Problem: COM weiß nicht a priori welche Schnittstellen von jedem Objekt unterstützt werden. Die .NET-Runtime kennt das auch nicht - jedenfalls nicht von COM. Die einzige Möglichkeit, die .NET kennt, wäre, wenn die Typbibliothek für das Objekt angibt, dass das zurückgegebene Objekt von einer bestimmten Schnittstelle stammt. Es fehlt Ihnen nur ein IUNKNOWN-Pointer und Sie müssen über Code nach bestimmten Schnittstellen fragen, ob Sie eine andere Antwort als NULL erhalten.

Da der Typ des SelectedItem propery Objekt ist, bedeutet dies, dass die Typenbibliothek einfach sagt „der Rückgabetyp eine Schnittstelle Zeiger vom Typ IUnknown ist“ (es IDispatch sein könnte, aber das Prinzip steht). Der genaue Typ hängt natürlich von den Laufzeitbedingungen ab - "was gerade ausgewählt wird".

(In .NET ist der Rückgabetyp tatsächlich System.__ComObject, weil Sie nicht einen nackten Interface-Zeiger aber einen COM Callable Wrapper, der ein .NET-basierter Proxy für das Objekt erhalten haben) von

Sie sind auf Gedeih und Verderb die (schlechte?) Dokumentation der Bibliothek, um einen Hinweis darauf zu erhalten, welche Arten von Schnittstellen das zurückgegebene Objekt unterstützen könnte. Wenn Sie das nicht tun, könnte Code wie Chibacity Ihnen auch eine unvollständige Liste bringen (ich habe diesen Code nicht überprüft). Letztendlich möchten Sie diesen Code wahrscheinlich verwenden, um beim Debuggen eine Liste der Kandidatenschnittstellen zu erhalten.

Sobald Sie ein paar Möglichkeiten kennen, die Sie interessieren, können Sie sich Tippfehler ersparen, indem Sie einfach den C# as-Operator verwenden (wodurch der COM-Callable-Wrapper die entsprechenden COM-Spells für das native Objekt ausgibt).

1

ich aggree, dass die Dokumentation wird an bestimmten Stellen fehlt aber die Hilfe ist ziemlich spezifisch in Ihrem Fall:

Bemerkungen

Diese Eigenschaft einen Verweis auf das aktuell ausgewählte Element zurück in die Inhaltsverzeichnis.Die Rückgabe ist ein IUnknown, da dort mehrere mögliche Objekte sind, die das ausgewählte Objekt sein kann.

Wenn in der Registerkarte Anzeige arbeiten, könnte der Verweis auf ein Karte Objekt sein, wenn Sie einen Datenrahmen, Schicht Objekte (FeatureLayer, FDOGraphicsLayer, usw.), wenn Sie eine Ebene ausgewählt haben haben eine der ausgewählt oder ein LegendGroup, wenn Sie einen eindeutigen Wert oder eine Überschrift ausgewählt haben.

In der Registerkarte Quelle kann die Referenz plus eine Tabelle, FeatureDataset oder Workspace einem der oben genannten Aufgaben sein.

Wenn mehr als ein Element ausgewählt ist, lautet die Referenz ein Set Objekt.

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#/SelectedItem_Property/000v00000124000000/

Verwandte Themen