Reputation: 27516
I have a COM object 'Foo' that defines a function returning an array of Bar:
public Bar[] Bars()
{
return bars;
}
This is in a DLL that's registered with COM.
I can call this from VBA like so:
Dim aBars() As Bar
aBars = oFoo.Bars()
Dim oBar As Bar
Set oBar = aBars(0)
However, I need to call the same function from VBScript, which has no early binding support, and when I try this, it fails:
Dim aBars
aBars = oFoo.Bars()
Dim oBar
Set oBar = aBars(0) ' fails with 'Type Mismatch'
If I inspect the type of 'aBars', it is 'Unknown()', which I guess is why it doesn't know what to do with it.
What can I do to make this work?
Upvotes: 3
Views: 288
Reputation: 138841
You need to return a class that's ComVisible (and enumerable), for example, this:
public Array Bars()
{
return bars;
}
or an ArrayList, something like this:
public ArrayList Bars()
{
ArrayList list = new ArrayList();
// etc...
return list;
}
or if you don't like ArrayList, something like this:
public BarList Bars()
{
BarList list = new BarList();
// etc...
return list;
}
[ComVisible(true)]
public class BarList : List<Bar>
{
}
Upvotes: 0
Reputation: 941407
There is something wrong with the attributes on the Bar class or interface, it doesn't implement IDispatch like scripting languages require. Only IUnknown, something that VBA can handle but VBScript can't. IDispatch is required to support late binding, as needed by scripting runtimes.
I can't see Bar at all so have to guess. If it is an interface or a class that implements an interface then you need [InterfaceType(ComInterfaceType.InterfaceIsDual)]
to get support for both early and late binding. Or ComInterfaceType.InterfaceIsIDispatch for late binding.
If it is a class then you need [ClassInterface(ClassInterfaceType.AutoDual)]
to get support for early and late. Or ClassInterfaceType.AutoDispatch for late.
Boilerplate stay-out-of-trouble is:
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IBar {
// etc...
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class Bar : IBar {
// etc...
}
Which supports both early and late binding and is a good way to hide the class implementation details, a strong COM goal, avoiding the baggage that gets pulled in from the base class of Bar, the System.Object methods.
Upvotes: 1