2010-04-26 27 views
7

Hasta ahora, siempre he decorado mis clases .NET que quiero usar desde VB6 con el atributo [AutoDual]. El objetivo era obtener Intellisense en objetos .NET en el entorno VB6. Sin embargo, el otro día busqué en Google AutoDual y la primera respuesta es 'No usar AutoDual'.¿Por qué no debería usar AutoDual?

He buscado una explicación coherente de por qué no debería usarlo, pero no pude encontrarlo.

¿Alguien puede explicarlo?

Respuesta

8

creo que esto lo resume:

tipos que utilizan una interfaz dual permitirá clientes para unirse a un diseño interfaz específica. Cualquier cambio en una versión futura de al diseño del tipo o cualquier tipo base romperá los clientes COM que se enlazan a la interfaz. Por predeterminado, si el atributo ClassInterfaceAttribute es no especificado, se utiliza una interfaz de envío .

http://msdn.microsoft.com/en-us/library/ms182205.aspx

que aumenta la posibilidad de que cambiar algo en esa clase con el doble atributo de auto va a romper el código de otra persona cuando se cambia la clase. Si le da al consumidor la capacidad de hacer algo que posiblemente les cause problemas en el futuro.

La siguiente opción es ClassInterfaceType.AutoDual. Esta es la manera rápida y sucia de obtener soporte de enlace anticipado también (y hacer que los métodos aparezcan en VB6 IntelliSense). Pero también es fácil romper la compatibilidad, cambiando el orden de los métodos o agregando nuevas sobrecargas. Evite usar AutoDual.

http://www.dotnetinterop.com/faq/?q=ClassInterface

fin he encontrado el enlace que habla de lo que está pasando con AutoDual y cómo funciona:

http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/7fa723e4-f884-41dd-9405-1f68afc72597

La advertencia contra AutoDual no es el hecho de que las interfaces duales son malas, pero el hecho de que auto-genera la interfaz COM para usted. Eso es malo. Cada vez que la interfaz COM tiene que ser regenerada, obtendrá un nuevo GUID y miembros potencialmente nuevos. Si cambia el GUID , obtendrá una nueva interfaz/clase en la medida en que COM es en cuestión. Para el enlace anticipado, debe tener que reconstruir los clientes cada vez que se regeneró la interfaz. El enfoque preferido de es definir la interfaz de clase COM explícitamente con un GUID . Entonces, todos los clientes vinculantes iniciales de pueden usar la interfaz definida y no preocuparse porque cambie en durante el desarrollo. Es por eso que la opción recomendada es Ninguna para indicar CLR no generar automáticamente para usted. Sin embargo, puede implementar la interfaz dual si la necesita.

+0

La parte que no tengo clara es la siguiente: 'Cualquier cambio en una versión futura del diseño del tipo o cualquier tipo base romperá los clientes COM '. Es decir, si cambio una propiedad de int a double, ¿el cliente se romperá? ¿O significa que si simplemente recompilo la pieza .NET, el cliente VB6 ya no podrá consumirlo? – AngryHacker

+0

Siempre y cuando no cambie la interfaz, debería estar bien. http://www.dotnetinterop.com/faq/?q=ClassInterface – kemiller2002

+0

@Kevin, por lo que simplemente recompilar mi biblioteca .NET no afectará al consumidor que? ¿Y qué significa 'cambiar el orden de los métodos 'realmente? ¿Quiere decir cambiar el orden de los métodos en el código? Todavía no entiendo bien por qué deberíamos evitar AutoDual. Creo que se entiende que si cambias la interfaz, entonces el consumidor no va a funcionar. Siempre ha sido así en el mundo de VB6. – AngryHacker

11

Encontré una manera confiable de proporcionar Intellisense para objetos .NET en VB6, mientras que al mismo tiempo no se rompe la interfaz. La clave es marcar cada método/propiedad público en la interfaz con DispatchID. Entonces la clase debe heredar de esta interfaz, de la manera a continuación.

[Guid("BE5E0B60-F855-478E-9BE2-AA9FD945F177")] 
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 
public interface ICriteria 
{ 
    [DispId(1)] 
    int ID { get; set; } 
    [DispId(2)] 
    string RateCardName { get; set; } 
    [DispId(3)] 
    string ElectionType { get; set; } 
} 


[Guid("3023F3F0-204C-411F-86CB-E6730B5F186B")]  
[ClassInterface(ClassInterfaceType.None)] 
[ProgId("MyNameSpace.Criteria")] 
public class Criteria : ICriteria 
{ 
    public int ID { get; set; } 
    public string RateCardName { get; set; } 
    public string ElectionType { get; set; } 
} 

Lo que el identificador de envío le da es la capacidad de moverse alrededor de los elementos de la clase, además ahora se puede añadir cosas nuevas a la clase y no romper la compatibilidad binaria.

Cuestiones relacionadas