在system.Interactive.asenc中,用于IASYNCENUMETH的鸭子枚举的错误



我想知道为什么此代码 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);
    }
}

相关内容

  • 没有找到相关文章