2011-05-26 8 views
7

Tengo el control SAP RPC OCX que me gustaría usar. En C# 4 siguiente código funciona bien:Dinámico vs Typed produce resultados extraños

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);    
dynamic fc = System.Activator.CreateInstance(t, false); 
dynamic connection = fc.Connection; 
connection.System = ""; 

siguiente código no funciona (a pesar de que la conexión no es nulo)

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);    
dynamic fc = System.Activator.CreateInstance(t, false); 
var connection = fc.Connection as SAPLogonCtrl.Connection 
connection.System = ""; 

de error se lanza: "Intento de leer o escribir en la memoria protegida Esto a menudo es una indicación de que otra memoria está corrupta ".

El hecho más extraño es esto, sin embargo: se ejecuta

System.Type t = System.Type.GetTypeFromProgID("SAP.Functions", true);    
dynamic fc = System.Activator.CreateInstance(t, false); 
dynamic c1 = fc.Connection; 
var c2 = fc.Connection as SAPLogonCtrl.Connection; 
if (c1 == c2) 
    c2.System = ""; 

Última línea de tiros y la misma excepción !!! Reemplazar c2 con c1 funciona como se esperaba ...

Siento que me falta algo trivial y, sin embargo, estoy en una pérdida completa ... ¿Por favor ayuda?

Otros detalles: El cambio de :

dynamic fc = System.Activator.CreateInstance(t, false); 

a:

var fc = System.Activator.CreateInstance(t, false) as SAPFunctionsOCX.SAPFunctions; 

no hace ninguna diferencia. c1 todavía funciona y c2 todavía no funciona.

Información adicional n. ° 2: El cambio de propiedades en FC también funciona en ambos casos.

+0

Por favor, nos muestran lo que la siguiente vuelta: 'c1.GetType ToString()()' y 'c2.GetType (.) .ToString() '. –

+0

Ambos devuelven System .__ ComObject –

+0

Estoy haciendo una toma en la oscuridad aquí, pero tal vez 'fc.Connection' es en realidad una instancia de una clase heredada de' SAPLogonCtrl.Connection'. Es por eso que su 'como' no devuelve nulo y por qué está viendo un comportamiento diferente. A lo que Daniel intentaba llegar preguntando los tipos. – Greg

Respuesta

1

Aunque parece que está haciendo lo mismo en ambas ocasiones, en realidad es completamente diferente: En el primer ejemplo de código:

dynamic connection = fc.Connection; 
connection.System = ""; 

lo que sucede es que se consigue fc.Connection, y luego invoca el colocador System = propiedad usando dynamic. El tiempo de ejecución del lenguaje dinámico se desactiva y consulta las interfaces COM e invoca un método particular en una interfaz COM particular. Realmente no se puede ver qué interfaz o método está usando desde el lado C# de las cosas.

En el segundo ejemplo (He reemplazado el var para hacer las cosas más claras):

SAPLogonCtrl.Connection connection = fc.Connection as SAPLogonCtrl.Connection 
connection.System = ""; 

lo que sucede es que se consigue fc.Connection, y luego convertirlo a SAPLogonCtrl.Connection. A continuación, intente y llame al SAPLogonCtrl.Connection.System = y luego falla.

Sospecho que está fallando porque el objeto no es realmente una instancia de SAPLogonCtrl.Connection pero puede ser un proxy u otro objeto.

La mayor parte de la interoperabilidad COM está dividida en una interfaz (lo más probable es que sea SAPLogonCtrl.IConnection) y una clase. Cuando llame a métodos, generalmente necesita llamar al a través de la interfaz. El código dynamic hará todo por ti detrás de escena.

Puede intentar buscar la interfaz y llamar usando eso. Si termina que existe SAPLogonCtrl.IConnection, la solución puede ser como sigue.

var connection = fc.Connection as SAPLogonCtrl.IConnection // note the I! 
connection.System = ""; 

En cualquier caso, recuerde que debe llamar a través de la interfaz cuando se trata de la interoperabilidad COM

0

¿No puede simplemente agregar el control real como referencia a su proyecto y usarlo a través del código de interoperabilidad que crea Visual Studio, en lugar de tratar de crearlo a través de COM y reflexión?

+0

Eso es exactamente lo que hice: las clases mencionadas son todas generadas por Visual Studio. Si se refiere a "control de arrastre en el formulario", no puedo hacerlo ya que no es una aplicación de Windows Forms, aunque sospecho que el resultado será el mismo que generará el código que generará Visual Studio. –

0

Solo una idea pero dado que dynamic no está limitada hasta el tiempo de ejecución, mientras que var está vinculada en tiempo de compilación, ¿podría ser que el tipo de fc no está disponible para la conexión?

EDIT: Como una cuestión secundaria, ¿hay alguna necesidad de usar:

conexión var = fc.Connection como SAPLogonCtrl.Connection

donde sólo se puede usar: conexión

SAPLogonCtrl.Connection = fc.Connection;

¿Echo de menos algo? ¿Por qué lo configuraría como un tipo implícito y luego lo lanzaría explícitamente?

0

Debe tener en cuenta en el tiempo de ejecución ejecuciones dinámicas como un Objeto y Objeto puede aceptar cualquier cosa. Este simple hecho se señala en el Principio C# 4.0

Nota Inusualmente, el tipo dinámico solo existe en tiempo de compilación; en tiempo de ejecución, se utiliza el tipo System.Object en su lugar. Este es un detalle de implementación menor, pero que vale la pena recordar, ya que puede aclarar parte de la discusión que sigue. Una vez que tenga una variable dinámica, puede acceder a sus miembros (el código para obtener realmente un valor para la variable no se muestra aquí): myDynamicVar.DoSomething ("¡Con esto!");

Watson, Karli; Nagel, Christian; Pedersen, Jacob Hammer; Reid, Jon D .; Skinner, Morgan (2011-02-08). Inicio de Visual C# 2010 (Programador de Wrox para Programador) (p.414). Wrox. Versión Kindle.

+0

¿Cómo es útil? –

Cuestiones relacionadas