M
mjdryden
I have a bit of a complicated mix of COM and .Net here, so bear with
me while I explain
We have a Type Library that defines all of the interfaces used in this
project (a rather large one at that) which was created in VB6. For a
number of unrelated reasons, we've chosen to create new .Net classes
that implement these interfaces, which are, for the most part, working
correctly. We are able to pass our new objects into our COM classes
and perform most operations on them, with one major exception:
Enumeration.
Enumeration is defined in the existing type library.
In VB6 it appears as: IObject_NewEnum() as stdole.IUnknown
In .Net, it maps to: System.Collections.IEnumerator GetEnumerator()
I've created an internal Enumerator class on the .Net side to support
the enumeration, and it works correctly when enumerating from .Net,
however, when attempting to enumerate from VB6, I receive: ErrorCode
-2146827864 "Object Required". Looping through the objects by index
works correctly in both .Net and VB6.
Based on search results, I've tried adding [DispId(-4)] to the
GetEnumerator() method, which is apparently supposed to direct .Net to
output the enumerator as an EnumVariant, but I've had no success
here. My belief is that this isn't working because DispId needs to be
specified on the interface, however, I do not have access to change
this; I'm only able to work with the implementation (in either case,
I'm not certain how, or if, this could be done on a VB6 interface
anyway).
Ideally, I'm looking for a solution which does not require a change to
the type library. Is there another way to force C# to output the
enumerator in a format which VB can understand?
Or, if there is no other way than to change the interface, is there a
way to provide this directive in VB6?
Any suggestions are appreciated, but please keep in mind that getting
authority to change the VB6 type library will be extremely difficult,
and possibly not an option at all...if its not, my only recourse will
be to go back to utilizing the poorly written-hard to work with (and
equally unmodifiable) VB6 classes...something I'd really like to avoid
doing.
Some basic code:
public class IBFields : TBWApplication.IFields
{
[snip]
[System.Runtime.InteropServices.DispId(-4)]
public System.Collections.IEnumerator GetEnumerator()
{
return new FieldEnumerator(m_fieldsArray);
}
}
internal class FieldEnumerator : System.Collections.IEnumerator
{
private SortedList<string, IBField> m_fields;
int position = -1;
public FieldEnumerator(SortedList<string, IBField> list)
{
m_fields = list;
}
public object Current
{
get
{
try
{
return
(TBWApplication.IField)m_fields.Values[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public bool MoveNext()
{
position++;
return (position < m_fields.Count);
}
public void Reset()
{
position = -1;
}
}
me while I explain
We have a Type Library that defines all of the interfaces used in this
project (a rather large one at that) which was created in VB6. For a
number of unrelated reasons, we've chosen to create new .Net classes
that implement these interfaces, which are, for the most part, working
correctly. We are able to pass our new objects into our COM classes
and perform most operations on them, with one major exception:
Enumeration.
Enumeration is defined in the existing type library.
In VB6 it appears as: IObject_NewEnum() as stdole.IUnknown
In .Net, it maps to: System.Collections.IEnumerator GetEnumerator()
I've created an internal Enumerator class on the .Net side to support
the enumeration, and it works correctly when enumerating from .Net,
however, when attempting to enumerate from VB6, I receive: ErrorCode
-2146827864 "Object Required". Looping through the objects by index
works correctly in both .Net and VB6.
Based on search results, I've tried adding [DispId(-4)] to the
GetEnumerator() method, which is apparently supposed to direct .Net to
output the enumerator as an EnumVariant, but I've had no success
here. My belief is that this isn't working because DispId needs to be
specified on the interface, however, I do not have access to change
this; I'm only able to work with the implementation (in either case,
I'm not certain how, or if, this could be done on a VB6 interface
anyway).
Ideally, I'm looking for a solution which does not require a change to
the type library. Is there another way to force C# to output the
enumerator in a format which VB can understand?
Or, if there is no other way than to change the interface, is there a
way to provide this directive in VB6?
Any suggestions are appreciated, but please keep in mind that getting
authority to change the VB6 type library will be extremely difficult,
and possibly not an option at all...if its not, my only recourse will
be to go back to utilizing the poorly written-hard to work with (and
equally unmodifiable) VB6 classes...something I'd really like to avoid
doing.
Some basic code:
public class IBFields : TBWApplication.IFields
{
[snip]
[System.Runtime.InteropServices.DispId(-4)]
public System.Collections.IEnumerator GetEnumerator()
{
return new FieldEnumerator(m_fieldsArray);
}
}
internal class FieldEnumerator : System.Collections.IEnumerator
{
private SortedList<string, IBField> m_fields;
int position = -1;
public FieldEnumerator(SortedList<string, IBField> list)
{
m_fields = list;
}
public object Current
{
get
{
try
{
return
(TBWApplication.IField)m_fields.Values[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public bool MoveNext()
{
position++;
return (position < m_fields.Count);
}
public void Reset()
{
position = -1;
}
}