2010-01-08 4 views
6

Quelle est la bonne façon de passer un tableau de classes définies par l'utilisateur de vba à .net (en particulier C#) en utilisant com-interop?Passez un tableau de vba à C# en utilisant com-interop

Voici mon code C#. Si j'appelle Method1 de vba, il échoue avec "Array ou type défini par l'utilisateur attendu" ou "Fonction utilise un type d'automatisation non pris en charge dans Visual basic".

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

J'ai lu un peu à propos de la classe MarshallAsAttribute. Serait-ce la pièce manquante dans le code C#?

Voici le code vba J'utilise:

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

Nous avions besoin d'un peu plus d'infos ici. Pourriez-vous ajouter la définition VBA du type et du code indiquant que vous appelez l'interface COM? – JaredPar

+0

Ajout du code vba. – Freddie

+0

Votre déclaration de tableau déclare un tableau de variantes - il doit déclarer un tableau de votre UserDefinedClass, par ex. "Dim myArray (0 à 3) comme UserDefinedClass" – Joe

Répondre

4

IIRC vous devez passer des tableaux par référence.

Essayez de déclarer votre méthode comme

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

Si vous ne voulez pas polluer votre classe avec des paramètres ref pour les clients .NET, vous pouvez définir une interface ComVisible être utilisé par les clients COM, et la mettre en oeuvre explicitement ainsi:

[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 réponse au commentaire ** Si vous souhaitez exposer une collection à la place d'un tableau VBA, il vous suffit d'exposer recenseur, et toute autre méthode que vous voulez le code VBA être en mesure d'appeler (par exemple Ajouter, Re déplacer, Insérer, Effacer, ...). Par exemple.

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

    int Count { get; }; 

    IUserDefinedClass this[int index] { get; } 

    int Add(IUserDefinedClass item); 

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

Vous pouvez alors l'utiliser comme d'habitude dans VBA:

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

Next nIndex 
+0

J'ai essayé, mais je n'ai pas explicitement essayé d'ajouter la clause 'in'. Je vais donner un coup de feu aussi. en utilisant 'ref UserDefinedClass [] foo' a abouti à la même erreur, j'ai peur. – Freddie

+0

Donc, vous dites que je ne devrais pas avoir besoin d'inclure des attributs supplémentaires sur le paramètre 'Parameters'. J'ai vu d'autres codes qui utilisent des MarshallAs ici, mais comme je l'ai mentionné, cela ne semblait pas fonctionner dans mon scénario. – Freddie

+0

"Donc, vous dites que ..." - Je sais que vous avez besoin de ref pour les arguments de tableau de types primitifs. L'attribut [In] affecte la génération de l'IDL et n'est pas nécessaire. J'utiliserais normalement un type de collection pour passer des classes définies par l'utilisateur à VBA (classe publique MyUserDefinedClassCollection: Collection ), donc je n'ai pas essayé cela. – Joe