我想知道为什么此代码 IAsyncEnumerable<>
dynamic duckAsyncEnumerable = new int[0].ToAsyncEnumerable();
var duckAsyncEnumerator = duckAsyncEnumerable.GetEnumerator();
提出一个例外:
'对象'不包含" getEnumerator"的定义
IEnumerable<>
的相同代码正常。此外,通过反射的IAsyncEnumerable<>
的实施也可以正常工作。在.NET和.NET CORE。
IOutputFormatter
实现所需的此代码,该代码将源数据作为对象并必须遍历它。
dotnetfiddle中的示例
调用new int[0].ToAsyncEnumerable()
将返回(内部)类型AsyncIListEnumerableAdapter<int>
。这种类型的实现了IEnumerable<int>
,因此具有IEnumerable<int>.GetEnumerator()
方法。但是,它使用显式接口实现来实现此方法。
当您通过dynamic
调用时,无法明确实现的接口方法(它是私有的)。要访问该方法,您将必须首先将引用对接口的引用,如本答案中所述的问题使用Dynamic对象。。
我得到了解决方案。一个对象具有扩展方法ToAsyncEnumerable
返回IAsyncEnumerable<object>
。因此,我们可以迭代它:
public async Task Process(object source)
{
using (var enumerator = source.ToAsyncEnumerable().GetEnumerator())
{
while (await enumerator.MoveNext())
{
var item = enumerator.Current;
}
}
}
可以创建服用IAsyncEnumerable<T>
并实现IAsyncEnumerable<object>
的包装器。Activator
在扩展方法中创建包装器。这是实现:
public class AsyncEnumerable<T> : IAsyncEnumerable<object>
{
private IAsyncEnumerable<T> _source;
public AsyncEnumerable(IAsyncEnumerable<T> source)
{
_source = source;
}
public IAsyncEnumerator<object> GetEnumerator()
{
return new AsyncEnumerator<T>(_source.GetEnumerator());
}
}
public class AsyncEnumerator<T> : IAsyncEnumerator<object>
{
private IAsyncEnumerator<T> _source;
public AsyncEnumerator(IAsyncEnumerator<T> source)
{
_source = source;
}
public object Current => _source.Current;
public void Dispose()
{
_source.Dispose();
}
public async Task<bool> MoveNext(CancellationToken cancellationToken)
{
return await _source.MoveNext(cancellationToken);
}
}
public static class AsyncEnumerationExtensions
{
public static IAsyncEnumerable<object> ToAsyncEnumerable(this object source)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
else if (!source.GetType().GetInterfaces().Any(i => i.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>)))
{
throw new ArgumentException("IAsyncEnumerable<> expected", nameof(source));
}
var dataType = source.GetType()
.GetInterfaces()
.First(i => i.GetGenericTypeDefinition() == typeof(IAsyncEnumerable<>))
.GetGenericArguments()[0];
var collectionType = typeof(AsyncEnumerable<>).MakeGenericType(dataType);
return (IAsyncEnumerable<object>)Activator.CreateInstance(collectionType, source);
}
}