2010-01-08 22 views
6

¿Cuál es la forma correcta de pasar una matriz de clases definidas por el usuario de vba a .net (específicamente C#) usando com-interop?Pase una matriz de vba a C# utilizando com-interop

Aquí está mi código C#. Si llamo a Method1 desde vba, está fallando con "Array o el tipo definido por el usuario esperado" o "La función usa un tipo de automatización no compatible con Visual Basic".

public class MyClass 
{ 
    public Method1(UserDefinedClass[] Parameters) { ... } 
    public Method2(Object Parameters) { ... } 
} 

He leído un poco sobre la clase MarshallAsAttribute. ¿Podría ser esta la pieza faltante en el código C#?

Aquí está el código VBA que estoy usando:

Dim udt As New UserDefinedClass 
Dim myArray() 
myArray(1) = udt 
myClass.Method1(myArray) 
myClass.Method2(myArray) 
+0

que íbamos a necesitar un poco más información aquí. ¿Podría agregar la definición de VBA del tipo y algún código que muestre que llama a la interfaz COM? – JaredPar

+0

Agregado código vba. – Freddie

+0

La declaración de matriz declara una matriz de variantes; debería declarar una matriz de UserDefinedClass, p. Ej. "Dim myArray (0 a 3) como UserDefinedClass" – Joe

Respuesta

4

IIRC usted tiene que pasar matrices por referencia.

Trate declarar su método

public class MyClass 
{ 
    public void Method1([In] ref UserDefinedClass[] Parameters) { ... } 
    ... 
} 

Si no quiere contaminar su clase con parámetros árbitro para clientes .NET, puede definir una interfaz ComVisible para ser utilizado por los clientes COM, y aplicarlo explícita así:

[ComVisible(true)] 
public interface IMyClass 
{ 
    void Method1([In] ref UserDefinedClass[] Parameters) { ... } 
    ... 
} 

public class MyClass : IMyClass 
{ 
    void IMyClass.Method1(ref UserDefinedClass[] Parameters) 
    { 
     this.Method1(Parameters); 
    } 

    public Method1(UserDefinedClass[] Parameters) 
    { 
     ... 
    } 
} 

** En respuesta al comentario ** Si desea exponer una colección lugar de una matriz de VBA, sólo tiene que exponer a un empadronador, y cualquier otro método que desea que el código VBA para poder llamar (por ejemplo, Agregar, Re mover, Insertar, Borrar, ...). P.ej.

[ComVisible] 
public interface IUserDefinedClassCollection 
{ 
    IEnumerator GetEnumerator(); 

    int Count { get; }; 

    IUserDefinedClass this[int index] { get; } 

    int Add(IUserDefinedClass item); 

    // etc, other methods like Remove, Clear, ... 
} 

Luego, puede usarlo como de costumbre en VBA:

Dim objUserDefinedClasses As UserDefinedClassCollection 
... 
objUserDefinedClasses.Add objUserDefinedClass 
... 
For nIndex = 0 To objUserDefinedClasses.Count 

Next nIndex 
+0

Lo he intentado, pero no he intentado explícitamente agregar la cláusula 'in'. Voy a dar una oportunidad también. usar 'ref UserDefinedClass [] foo' resultó en el mismo error, me temo. – Freddie

+0

Entonces, estás diciendo que no debería necesitar incluir ningún atributo adicional en el parámetro 'Parámetros'. He visto otro código que usa MarshallAs aquí, pero como mencioné, eso no pareció funcionar en mi escenario. – Freddie

+0

"Entonces, estás diciendo que ..." - Sé que necesitas ref para argumentos de matriz de tipos primitivos. El atributo [In] afecta la generación del IDL y no es necesario. Normalmente usaría un tipo de colección para pasar clases definidas por el usuario a VBA (clase pública MyUserDefinedClassCollection: Collection ), así que no lo he intentado. – Joe