una qué que programacion polimorfico metodos llamar herencia evento ejemplos ejemplo clases clase c# javascript .net com webbrowser-control

c# - qué - que es una clase en programacion



Pasar una instancia de clase C#a código administrado desde JavaScript a través de COM (2)

Tienes que hacer dos cosas

  1. Descubre el tipo de objeto como se describe aquí .

  2. Extraiga el objeto real de él usando Marshal.GetObjectForIUnknown (lea hasta el final, hay una interfaz para implementar).

El esquema básico de mi problema se muestra en el código a continuación. Estoy alojando un control WebBrowser en un formulario y proporcionando un ObjectForScripting con dos métodos: GiveMeAGizmo y GiveMeAGizmoUser . Ambos métodos devuelven las instancias de clase respectivas:

[ComVisible] public class Gizmo { public string name { get; set; } } [ComVisible] public class GizmoUser { public void doSomethingWith(object oGizmo) { Gizmo g = (Gizmo) oGizmo; System.Diagnostics.Debug.WriteLine(g.name); } }

En JavaScript, creo una instancia de ambas clases, pero necesito pasar la primera instancia a un método en la segunda instancia. El código JS se ve un poco así:

var // Returns a Gizmo instance gizmo = window.external.GiveMeAGizmo(), // Returns a GizmoUser instance gUser = window.external.GiveMeAGizmoUser(); gizmo.name = ''hello''; // Passes Gizmo instance back to C# code gUser.doSomethingWith(gizmo);

Aquí es donde choqué contra una pared. Mi método C # GizmoUser.doSomethingWith() no puede devolver el objeto a un tipo de Gizmo. Lanza el siguiente error:

No se ha podido convertir el objeto COM del tipo ''System .__ ComObject'' al tipo de interfaz ''Gizmo''

Inseguro de cómo proceder, intenté un par de otras cosas:

  • Safe casting Gizmo g = oGizmo as Gizmo; ( g es null )
  • Hacer que las clases implementen IDispatch y InvokeMember a InvokeMember , como se explica aquí . El miembro "nombre" es null .

Necesito que esto funcione con la versión de .NET Framework menor que 4.0, por lo que no puedo usar dynamic . ¿Alguien sabe cómo puedo hacer que esto funcione?


Que interesante. Cuando recibimos el objeto oGizmo en doSomethingWith , es del tipo Windows Runtime Object . Este comportamiento es coherente entre JavaScript y VBScript.

Ahora, si especificamos explícitamente MarshalAs(UnmanagedType.IUnknown) en el valor de retorno del método GiveMeAGizmo() , todo funciona bien , el objeto puede ser devuelto a Gizmo dentro de doSomethingWith :

[ComVisible(true), ClassInterface(ClassInterfaceType.AutoDispatch)] public class ObjectForScripting { [return: MarshalAs(UnmanagedType.IUnknown)] public object GiveMeAGizmo() { return new Gizmo(); } public object GiveMeAGizmoUser() { return new GizmoUser(); } }

Aún así, si especificamos UnmanagedType.IDispatch o UnmanagedType.Struct (el predeterminado que clasifica el objeto como COM VARIANT ), el problema está de vuelta.

Por lo tanto, hay una solución, pero no hay una explicación razonable para dicho comportamiento de interoperabilidad COM, hasta el momento.

[ACTUALIZACIÓN] Algunos experimentos más, a continuación. Observe cómo la obtención de gizmo1 es exitosa, mientras que gizmo2 no es:

C # :

// pass a Gizmo object to JavaScript this.webBrowser.Document.InvokeScript("SetGizmo", new Object[] { new Gizmo()}); // get it back, this works var gizmo1 = (Gizmo)this.webBrowser.Document.InvokeScript("GetGizmo"); // get a new Gizmo, via window.external.GiveMeAGizmo() // this fails var gizmo2 = (Gizmo)this.webBrowser.Document.InvokeScript("GetGizmo2");

JavaScript:

var _gizmo; function SetGizmo(gizmo) { _gizmo = gizmo; } function GetGizmo() { return _gizmo; } function GetGizmo2() { return window.external.GiveMeAGizmo(); }

Es solo una suposición, pero creo que dicho comportamiento podría tener algo que ver con los conjuntos de permisos de seguridad .NET, impuestos por WebBrowser.ObjectForScripting .