"Nikolay Belyh" <nb****@gmail.comwrote in message
news:11**********************************@t1g2000p ra.googlegroups.com...
On 27 ÄÅË, 05:10, Greg <gcad...@gmail.comwrote:
Greg, thank you for reply.
Did you try adding the 'this[ ]' indexer and setting that as your
default property by decorating it with DefaultPropertyAttribute?
I did not try DefaultPropertyAttribute, since AFAIK it is unrelated to
COM after all.. But now I did :-)
Still no luck. What I did try before is trying to use [DispId(0)]
attribute on indexer. Withe the same (negative) result though..
On the other hand, I'm surprised this 'almost' worked since the
VBA.CreateObject() method call is explicitly used for COM objects, and
by the looks of your code, it doesn't appear to be exposed to COM. The
reason it works for Excel is because Excel is a COM object.
The assembly is made visible for COM using project settings. I mean, 2
chekcboxes
"Make assembly COM-visible" and "Register for COM interop" in project
settings.
I have also tried to make the COM type library for the assembly look
exactly as Excel's one
in the part of enumerator implementation. Though it did not work
either, below is the code I tried:
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace ClassLibrary2
{
public interface IMyColl
{
[DispId(-4)]
object _NewEnum
{
[return: MarshalAs(UnmanagedType.IUnknown)]
get;
}
[DispId(0)]
[IndexerName("_Default")]
object this[int index]
{
get;
}
}
public class X {}
[ComDefaultInterface(typeof(IMyColl))]
[ClassInterface(ClassInterfaceType.None)]
public class MyColl : IMyColl
{
ArrayList items;
public MyColl()
{
items = new ArrayList(new object[] { new X(), new X(), new
X() });
}
public object _NewEnum
{
get { return items.GetEnumerator(); }
}
public object this[int index]
{
get
{
return items[index];
}
}
}
public interface IMyClass
{
MyColl objs { get; }
}
[ComDefaultInterface(typeof(IMyClass))]
[ClassInterface(ClassInterfaceType.None)]
public class Class1 : IMyClass
{
public MyColl objs
{
get { return new MyColl(); }
}
}
}
This way it works when target environment sees the type library (from
Excel VBA for example)
But it still does not work from the script.
You won't be able to use the indexer syntax on a .NET collection like you do
on a COM collection without some hand code interface trickery. Note that
..NET collections are not exactly like COM collections, for instance the
default lower bound is 0, while it's 1 for COM (try Worksheets(0)).
If you change your code a bit like this:
using System;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace ClassLibrary2
{
public interface IMyColl : IEnumerable // (1)
{
[DispId(-4)]
new IEnumerator GetEnumerator(); // (2)
[DispId(1)] // (3)
int Count
{
get;
}
[DispId(0)]
object this[int index]
{
get;
}
}
public class X { // (4)
int _val;
public int Val
{
get
{
return _val;
}
}
}
[ComDefaultInterface(typeof(IMyColl))]
[ClassInterface(ClassInterfaceType.None)]
public class MyColl : IMyColl
{
ArrayList items;
public MyColl()
{
items = new ArrayList(new object[] { new X(), new X(), new
X() });
}
public IEnumerator GetEnumerator()
{
return items.GetEnumerator();
}
public int Count
{
get { return items.Count;}
}
public object this[int index]
{
get
{
return items[index];
}
}
}
public interface IMyClass
{
MyColl objs { get; }
}
[ComDefaultInterface(typeof(IMyClass))]
[ClassInterface(ClassInterfaceType.None)]
public class Class1 : IMyClass
{
public MyColl objs
{
get { return new MyColl(); }
}
}
}
You will be able to use this class from VBscript like this:
Dim obj, x
Set obj = Wscript.CreateObject("ClassLibrary2.Class1")
Set coll = obj.objs
For Each v in coll
WScript.Echo v.Val
Next
WScript.Echo coll.Count
For i = 0 To coll.Count - 1 'lower bound is 0!!
WScript.Echo x(i).Val
Next
Note that I set coll to obj.objs which is exposed as an IEnumVARIANT by the
COM Interop layer(wrapped in a VARIANT by the scripting engine).
You can use indexing syntax on the coll object to get a specific object from
the collection, while you can also For ... Each over the collection
Willy.