2011-03-31 10 views
7

Este realmente me tiene perplejo. Estoy trabajando con otro desarrollador que me llamó porque no podía creer lo que estaba viendo. Pasamos juntos con el depurador y lo vi también y no tuve ninguna explicación. Aquí está el escenario. Él está escribiendo un método que interactúa con una tercera objeto COM partido a través de un contenedor COM generada automáticamente (generada simplemente añadiendo el componente COM como una referencia Aquí está la parte superior de su método:.¿Cómo puede afectar la configuración de una variable cuyo ámbito de método C# afecta a otra?

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1); 
     string strCustom2 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2); 

El propósito de la el código es obtener un número de proyecto y un número de subproyecto de un objeto "documento" (oDoc).

Esto es lo que sucede a medida que avanza. Después de la primera asignación strCustom1 tiene el valor esperado "32344" (un número de proyecto) y strCustom2 está vacío como se esperaba. Después de la segunda asignación, strCustom2 obtiene el número de subproyecto "0002" - , pero strCustom1 se ha cambiado a 32334 - un carácter ha sido cambiado?

Me pareció algo así como un exceso de sobremuestreo de lenguaje c de la vieja escuela (que no esperaría en una aplicación administrada incluso si estaba interoperando con un componente COM). Todos estábamos desconcertados. En un intento de cortar alrededor de esta rareza, he tratado de copiar el contenido de la primera cadena a otra ubicación de este modo:

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
     string strCustom2 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 

mismos resultados! A estas alturas, nos aferrábamos a las pajas y dejamos caer el código de .NET 4 a .NET 3.5 (CLR 2) pero sin cambios. Un punto quizás relevante es que este es un servicio y nos estamos uniendo al proceso de servicio. La compilación apunta a x86 y la ubicación del servicio definitivamente está en la carpeta de generación de salida de depuración.

¿Hay alguna explicación lógica para esto? Estoy perplejo en cuanto a cómo proceder.

Respuesta

1

Parece que strCustom1 y strCustom2 se han establecido como referencias para el resultado de GetAttributeValueByID. No sé por qué, y sería interesante ver si alguien más aquí (Paginación Dr. Skeet jaja ...) puede.

A corto plazo, sin embargo, yo creo que usted encontrará esto va a resolver el problema para usted ...

public bool RefolderDocument(ref IManDocument oDoc) 
    { 
     string strCustom1 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
     string strCustom2 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 

Mi idea es, básicamente, para que se evalúe una expresión en lugar de trabajar con el referernce directamente ...

Martin.

Ps. ¿Qué pasa con el string.Copy()?

+0

'string.Copy' fue su intento de solucionar este extraño problema ... –

+0

Sí. String.Copy fue un intento de mover la ubicación de lo que strCustom1 apuntaba antes de que se sobrescribiera la ubicación de origen. Esperaba que esto funcionara. No fue así. –

1

Probables reglas de gestión de memoria COM no están siendo seguidas por el objeto COM y está sobrescribiendo la memoria que el CLR cree que posee. Cosas simples como no crear un nuevo objeto para GetEnumerator() realmente pueden arruinar la interoperabilidad COM y el almacenamiento en caché que hace.

También debe tener en cuenta que la forma en que la llamada COM funciona realmente es al pasar una referencia a la memoria para la cadena. Aunque se llame como:

str = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1) 

Es realmente llama más como:

hresult = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1,&str) 

Así se puede ver el objeto COM tiene un puntero a la derecha en la memoria CLR.

En otras palabras, mire el objeto COM, no su código .NET.

+0

Tony, Gracias por la respuesta. Desafortunadamente, el objeto COM es propiedad del proveedor y supuestamente ha sido probado. :-). ¡Lo que es interesante es el cambio de un solo personaje en el medio de la otra variable! Tal vez una de las alternativas sugeridas sea suficiente. –

+1

@Decker, sí, eso es desafortunado. Me encontré con muchos problemas con los DLL COM "probados" que fallan en .NET porque no siguen las reglas que la interoperabilidad COM espera. Temería la corrupción de la memoria si implementara las soluciones alternativas de copia; si tienes suerte, es solo un problema de depurador (que solo he visto en C++, no en .NET, pero otros están informando sobre .NET). Sugeriría probar el tipo dinámico si usa .NET 4.0 y vaya a través de la automatización automática, pero la fuente de los datos modificados debe ser entendida primero. –

0

No sé exactamente por qué o cómo está sucediendo esto y espero que alguien responda. Como solución alternativa, analizaría la cadena devuelta en un int y luego ejecutaría la segunda instrucción. Al menos eso evitará el problema del valor perdido.

int Custom1 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)); 
int Custom2 = int.Parse((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2)); 
1

He encontrado problemas similares al que usted ha descrito.

En mi caso, el .NET/compilador/runtine/CLR funcionaba muy bien, y el único problema era que el depurador visual studio mostraba valores incorrectos. Intenta escribir tus valores, p. a System.Diagnostics.Trace, o a la consola, para verificar si este es su caso.

+0

Esto es intrigante. No * pienso * este es el caso porque parece como si el valor realmente cambiara. De hecho, la forma en que llegamos a examinar esta sección del código fue debido a algún código de auditoría que detectó una discrepancia. Pero no está de más perjudicar arrojarlo a Trace para confirmar que no se trata de un problema de visualización del depurador. –

+0

Esto también iba a ser mi suposición. Escriba los valores en el registro en cada punto y analícelos de esa manera. No puedo ver cómo una cadena * copiada * puede cambiar. –

Cuestiones relacionadas