Die Verbindung zu COM-events in C# - Unterstützung für verwaltete und nicht verwaltete Server
Ich bin das schreiben von C# - code, der Verbindung von COM-Ereignissen. Ich habe implementiert die Verwendung von
Schnittstellen IConnectionPointContainer und IConnectionPoint so:
IConnectionPointContainer connectionPointContainer = internalGenerator as IConnectionPointContainer;
if (connectionPointContainer == null)
{
Debug.Fail("The script generator doesn't support the required interface - IConnectionPointContainer");
throw new InvalidCastException("The script generator doesn't support the required interface - IConnectionPointContainer");
}
Guid IID_IScriptGeneratorEvents = typeof(IScriptGeneratorCallback).GUID;
connectionPointContainer.FindConnectionPoint(ref IID_IScriptGeneratorEvents, out m_connectionPoint);
m_connectionPoint.Advise(this, out m_cookie);
Das problem ist, dass wenn der COM-server implementiert .Net (also C#), nach .Netto schafft es, verarbeitet es als ein .Net-Objekt, nicht ein COM-Objekt. Da die .Net-Objekt ist nicht implementiert, die IConnectionPointContainer-Schnittstelle, bekomme ich null wenn Sie versuchen, zu werfen das Objekt an die Oberfläche.
Irgendeine Idee, wie kann ich dies umgehen?
Ich kann natürlich IConnectionPointContainer implementieren von mir in der C# COM server, jedoch möchte ich eine einfachere Lösung, die ich kann leicht erklären, um anderen Entwicklern die Notwendigkeit der Umsetzung der COM-server.
P. S muss ich verwenden, IConnectionPointContainer als COM-server implementiert werden kann, in non-.Net (C++, Java).
Dank,
Inbar
InformationsquelleAutor Inbar Shani | 2008-11-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
IConnectionPointContainer ist implementiert auf der CCW (COM callable wrapper).NET automatisch erzeugt, wenn Sie Ihr .NET-Objekt als COM-Objekt extern.
Versuchen Sie anrufen Marschall.GetComInterfaceForObject auf die .NET-Objekt, um eine COM-Schnittstelle für die IConnectionPointContainer, anstatt einfach Gießen.
update ... und wenn das nicht funktioniert, Marschall.GetIUnknownForObject muss etwas zurückgeben, und vielleicht wird dann die Unterstützung einer Marschall.QueryInterface nennen.
InformationsquelleAutor Rob Walker
Hatte ich nicht einen Weg finden, dies zu tun.
Schließlich definiere ich eine andere Schnittstelle .Net und schreiben 2 code-Pfade, einen für .Net-Objekte und eines für echte COM-Objekte.
InformationsquelleAutor Inbar Shani
Das problem ist, dass dabei eine GetIUnknownForObject Aufruf liefert einen Zeiger, die Sie dann erfolgreich aufrufen zu erlangen IConnectionPointContainer für das Objekt mit der GUID. Aber, dass der Aufruf von QueryInterface dann gibt einfach das original .NET-Objekt, nicht ein IConnectionPointContainer-Schnittstelle.
Bin ich auch hängen geblieben, und wenn jemand irgendwelche weiteren Erkenntnisse bitte teilen. Mein Szenario ist, dass ich das aussetzen einer .NET-Steuerung als ein ActiveX mit COM-interop. Ich habe eine ComSourceInterface definiert für die Ereignissenke, aber in ein VB6-host, die Ereignisse sind nicht angeschlossen, wie erwartet. Ich bin daher versucht, um die IConnectionPointContainer-Schnittstelle für meine ausgesetzt .NET-Steuerung, um hook up die Ereignisse manuell, kann aber nicht bekommen, um diese Schnittstelle, wenn es tatsächlich umgesetzt wird - oder bin ich vielleicht einfach nur am falschen Objekt?
InformationsquelleAutor MarkS
Habe ich ein wenig weiter, ich habe das gleiche problem manuell verbinden Ereignisse bei der Belichtung ein .NET-Steuerung als ein ActiveX mit COM-interop.
Wenn Sie Graben ein wenig in der UserControl-Klasse mit dem Reflektor (z.B. Redgate Reflector), sehen Sie eine 'ActiveXImpl' geschachtelte Klasse, die enthält eine weitere geschachtelte statische Klasse namens 'AdviseHelper', die Mitglieder ComConnectionPointContainer und ComConnectionPoint. Es hat auch Hilfsfunktionen zu verbinden Punkte, wie Sie benötigen.
Gibt es ein problem. Wenn ein Ereignis verknüpft ist, die von COM-interop von Ihrer Steuerung (die Quelle), um die Verbindung Punkt Behälter (enthält die Ereignis-Senke für Ihr Steuerelement-Ereignisse), die IQuickActivate.QuickActivate Funktion aufgerufen wird, die ruft dann AdviseHelper Klasse' 'AdviseConnectionPoint" - Funktion.
Einen IUnknown-Schnittstellenzeiger auf das Ereignis Spüle, auf Ihrem client (also nicht Ihrer Kontrolle, die Sache, die Sie enthalten) wird an dieser QuickActivate-Funktion (parameter "pUnkEventSink'. Im Reflektor dieser Funktion sieht wie folgt aus, und ich habe markiert, wo tut es dem eigentlichen event hookup:
'PUnkEventSink' variable übergeben wird in dieser Funktion über die tagQACONTROL Struktur, aber wie Sie sehen können, im Gegensatz zu den IAdviseSink, Steuerelement-container, schriftart etc., diese variable wird nicht festgelegt, die jedes Mitglied der 'ActiveXImpl' - Klasse, und daher können Sie nicht bekommen, um es nach diese Funktion hat zunächst genannt worden, die das framework.
Müssen Sie Holen Sie sich dieses IUnknown pUnkEventSink variable zu nennen AdviseHelper.AdviseConnectionPoint () - Funktion, die das manuelle Ereignis-Anschluß. Und das ist das problem, das ich habe - leider kann man einfach nicht scheinen, zu fassen zu bekommen.
Jemand anderes hatte, keine weiteren Entwicklungen mit dies tun, lassen Sie es mich wissen!
InformationsquelleAutor MarkS
Ich weiß, ich bin ein wenig spät, aber ich war in der Lage, Ereignisse auffangen, um die Arbeit mit IConnectionPoint. Siehe meine Antwort hier. Insbesondere überprüfen Sie heraus die
MyAppDotNetWrapper
Klasse und wie es verwendet wird, wird der test.Letztlich denke ich, dass Ihr
m_connectionPoint.Advise(this, out m_cookie);
fehl, weilthis
muss[ComVisible(true)]
,[ClassInterface(ClassInterfaceType.None)]
undpublic
.InformationsquelleAutor MarkB42