Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 7 additions & 24 deletions src/coreclr/System.Private.CoreLib/src/System/__ComObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,24 +217,6 @@ RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTy
}
else if (interfaceType.Equals(typeof(IEnumerator).TypeHandle))
{
object? enumVariantImpl = GetData(typeof(IEnumeratorOverEnumVARIANTImpl));
if (enumVariantImpl is null)
{
IntPtr enumVariantPtr = IntPtr.Zero;
try
{ IEnumVARIANT enumVariant = (IEnumVARIANT)this;
enumVariantPtr = Marshal.GetIUnknownForObject(enumVariant);
enumVariantImpl = (IEnumerator)EnumeratorToEnumVariantMarshaler.GetInstance(null).MarshalNativeToManaged(enumVariantPtr);
}
finally
{
if (enumVariantPtr != IntPtr.Zero)
{
Marshal.Release(enumVariantPtr);
}
}
SetData(typeof(IEnumeratorOverEnumVARIANTImpl), enumVariantImpl);
}
return typeof(IEnumeratorOverEnumVARIANTImpl).TypeHandle;
}

Expand Down Expand Up @@ -313,24 +295,25 @@ private interface ICustomAdapterOverDispatchImpl : ICustomAdapter
[DynamicInterfaceCastableImplementation]
private interface IEnumeratorOverEnumVARIANTImpl : IEnumerator
{
private static IEnumerator GetEnumerator(__ComObject obj) =>
ComDataHelpers.GetOrCreateManagedViewFromComData<IEnumVARIANT, EnumeratorViewOfEnumVariant>(
obj, static enumVariant => new EnumeratorViewOfEnumVariant(enumVariant));

bool IEnumerator.MoveNext()
{
__ComObject co = (__ComObject)this;
return ((IEnumerator)co.GetData(typeof(IEnumeratorOverEnumVARIANTImpl))!).MoveNext();
return GetEnumerator((__ComObject)this).MoveNext();
}

void IEnumerator.Reset()
{
__ComObject co = (__ComObject)this;
((IEnumerator)co.GetData(typeof(IEnumeratorOverEnumVARIANTImpl))!).Reset();
GetEnumerator((__ComObject)this).Reset();
}

object IEnumerator.Current
{
get
{
__ComObject co = (__ComObject)this;
return ((IEnumerator)co.GetData(typeof(IEnumeratorOverEnumVARIANTImpl))!).Current;
return GetEnumerator((__ComObject)this).Current;
}
}
}
Expand Down
56 changes: 56 additions & 0 deletions src/tests/Interop/COM/Dynamic/CollectionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
namespace Dynamic
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Xunit;

internal class CollectionTest
Expand Down Expand Up @@ -81,6 +83,8 @@ private void CustomCollection()
Assert.Equal(array[2], obj.Item(2));
Assert.Equal(array.Length, obj.Count);

CustomEnumerator(array);

Console.WriteLine(" + Enumerate collection");
List<string> list = new List<string>();

Expand Down Expand Up @@ -135,6 +139,58 @@ private void CustomCollection()
Console.WriteLine(" + Clear collection");
obj.Clear();
Assert.Equal(0, obj.Count);
CustomEnumerator(System.Array.Empty<string>());
}

private void CustomEnumerator(string[] expected)
{
Console.WriteLine(" + Cast fresh COM enumerators to IEnumerator");
foreach (string firstMember in new[] { nameof(IEnumerator.MoveNext), nameof(IEnumerator.Reset), nameof(IEnumerator.Current) })
{
Console.WriteLine($" First member: {firstMember}, items: {expected.Length}");
object previous = null;
for (int pass = 0; pass < 3; pass++)
{
object enumVariant = obj._NewEnum;
Assert.True(Marshal.IsComObject(enumVariant));
Assert.NotSame(previous, enumVariant);
previous = enumVariant;
IEnumerator enumerator = (IEnumerator)enumVariant;
List<string> actual = new List<string>();

switch (firstMember)
{
case nameof(IEnumerator.MoveNext):
Assert.Equal(expected.Length != 0, enumerator.MoveNext());
if (expected.Length != 0)
{
actual.Add((string)enumerator.Current);
}
break;
case nameof(IEnumerator.Reset):
enumerator.Reset();
break;
case nameof(IEnumerator.Current):
Assert.Null(enumerator.Current);
break;
}

while (enumerator.MoveNext())
{
actual.Add((string)enumerator.Current);
}
AssertExtensions.CollectionEqual(expected, actual);
Assert.False(enumerator.MoveNext());

actual.Clear();
enumerator.Reset();
while (enumerator.MoveNext())
{
actual.Add((string)enumerator.Current);
}
AssertExtensions.CollectionEqual(expected, actual);
}
}
}

private void IndexChain()
Expand Down
Loading