2

我有一个异步方法,它使用传递给它的委托函数来处理数据读取器。委托的目的是从阅读器中构造域对象并将其返回给调用者。我想要一个构造委托和读取器的中间方法,并从被调用的方法返回结果 IAsyncEnumerable。我能够做到这一点的唯一方法是实际使用 IAsyncEnumerable 并从中间方法产生这些结果。尝试直接返回会导致编译器错误,指出我必须使用 yield return 或 yield break。

delegate T ProcessFunc<T>(MySqlDataReader reader);

async IAsyncEnumerable<T> ProcessReader<T>(MySqlDataReader reader, ProcessFunc<T> transformFunc)
{
    while (await reader.ReadAsync() != false)
    {
        yield return transformFunc(reader);
    }

    await reader.DisposeAsync();
}

public async IAsyncEnumerable<DataObject> GetDataObjectsAsync()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    var reader = await GetDataObjectsReaderAsync(); //Constructs appropriate sqlcommand and returns a mysqldatareader

    //only way i can get this to function
    //would like to just be able to write: return ProcessReader(reader, processFunc)
    //so as not to chain another enumerable
    await foreach (var obj in ProcessReader( reader, processFunc ))
        yield return obj; 
}
4

1 回答 1

1

在这种情况下,您可以将您的更改ProcessReader为接受Task<MySqlDataReader>,而不是MySqlDataReader让您GetDataObjectsAsync同步:

async IAsyncEnumerable<T> ProcessReader<T>(Task<MySqlDataReader> readerTask, ProcessFunc<T> transformFunc)
{
    var reader = await readerTask;
    while (await reader.ReadAsync() != false)
    {
        yield return transformFunc(reader);
    }

    await reader.DisposeAsync();
}

public IAsyncEnumerable<DataObject> GetDataObjects()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    return ProcessReader(GetDataObjectsReaderAsync(), processFunc)
}

或更改您的GetDataObjectsAsync方法以返回Task<IAsyncEnumerable<DataObject>>

public async Task<IAsyncEnumerable<DataObject>> GetDataObjectsAsync()
{
    ProcessFunc<DataObject> processFunc = (reader) =>
    {
        var id = reader.GetGuid( "id" );

        return new DataObject(id);
    };

    var reader = await GetDataObjectsReaderAsync(); //Constructs appropriate sqlcommand and returns a mysqldatareader

    return ProcessReader(reader, processFunc); 
}
于 2020-06-14T19:22:13.220 回答