我有一个IReliableDictionary,需要将字典中的项目带入IList以从我可靠的服务中返回。
似乎我无法执行任何类型的.ToList,所以我确定我正在错误地处理它。
public async Task<IList<CustomerOrderItem>> GetOrdersAsync()
{
IReliableDictionary<CustomerOrderItemId, CustomerOrderItem> orderItems =
await this.StateManager.GetOrAddAsync<IReliableDictionary<CustomerOrderItemId, CustomerOrderItem>>(CustomerOrderItemDictionaryName);
Dictionary<KeyValuePair<CustomerOrderItemId, CustomerOrderItem>, KeyValuePair<CustomerOrderItemId, CustomerOrderItem>> items = orderItems.ToDictionary(v => v);
IList<CustomerOrderItem> list = orderItems.ToList(); ???
...
}
关于如何从字典中取出项目并将其放入列表的任何想法?
[IReliableDictionary<K,V>
实现IEnumerable<KeyValuePair<K, V>>
,因此您可以执行ToList
。
也许确保名称空间已导入。
IReliableDictionary(就像IDictionary一样)是键值对的IEnumerable,所以您可以这样:
public async Task<IList<CustomerOrderItem>> GetOrdersAsync()
{
IReliableDictionary<CustomerOrderItemId, CustomerOrderItem> orderItems =
await this.StateManager.GetOrAddAsync<IReliableDictionary<CustomerOrderItemId, CustomerOrderItem>>(CustomerOrderItemDictionaryName);
var list = orderItems.Select(kvp => kvp.Value).ToList();
return list;
}
在编写此答案时,IAsyncEnumerable
是dotnet库的一部分,并且C#8.0添加了语法糖来支持它。
问题是ServiceFabric使用其自己的IAsyncEnumerable
定义,因此您不能对其应用dotnet扩展方法和C#助手。
我想出的一种解决方案是使用一个简单的包装器将ServiceFabric的IAsyncEnumerable
转换为本地的:
using System.Threading;
using System.Threading.Tasks;
using Generic = System.Collections.Generic;
using Fabric = Microsoft.ServiceFabric.Data;
public static class FabricAsyncEnumerableExtensions
{
/// <summary>
/// Converts ServiceFabric <see cref="Microsoft.ServiceFabric.Data.IAsyncEnumerable"/> to dotnet native <see cref="System.Collections.Generic.IAsyncEnumerable"/>.
/// </summary>
public static Generic.IAsyncEnumerable<T> ToGeneric<T>(this Fabric.IAsyncEnumerable<T> source) =>
new AsyncEnumerableWrapper<T>(source);
private class AsyncEnumerableWrapper<T> : Generic.IAsyncEnumerable<T>
{
private readonly Fabric.IAsyncEnumerable<T> _source;
public AsyncEnumerableWrapper(Fabric.IAsyncEnumerable<T> source) => _source = source;
public Generic.IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken _ = default)
{
Fabric.IAsyncEnumerator<T> enumerator = _source.GetAsyncEnumerator();
return new AsyncEnumeratorWrapper<T>(enumerator);
}
}
private class AsyncEnumeratorWrapper<T> : Generic.IAsyncEnumerator<T>
{
private readonly Fabric.IAsyncEnumerator<T> _source;
public AsyncEnumeratorWrapper(Fabric.IAsyncEnumerator<T> source) => _source = source;
public async ValueTask DisposeAsync() =>
await Task.Run(_source.Dispose).ConfigureAwait(false);
public async ValueTask<bool> MoveNextAsync() =>
await _source.MoveNextAsync(default).ConfigureAwait(false);
public T Current => _source.Current;
}
}
使用它就像调用扩展方法一样简单,然后将其用作常规的IAsyncEnumerable
:
Fabric.IAsyncEnumerable<KeyValuePair<Guid, Product>> asyncProducts = GetAsyncProducts();
return await asyncProducts.ToGeneric()
.Select(p => p.Value)
.ToListAsync()
.ConfigureAwait(false);