我们使用 AutoMapper ,我们的整个服务层都是异步。这是我们当前在API操作中的映射外观:
var response = (await this.service.GetAll())
.AsQueryable()
.ProjectTo<DataViewModel>();
...
我想实现以下目标:
var response = await this.service
.GetAll()
.Map<DataViewModel>();
到目前为止,我取得的最好成绩是:
var response = await this.service
.GetAll()
.Map<DataServiceModel, DataViewModel>();
扩展方法如下:
// Task extension
public static async Task<IEnumerable<TDestination>> MapCollection<TSource, TDestination>(
this Task<IEnumerable<TSource>> collection)
=> (await collection)
.MapCollection<TDestination>();
// IEnumerable extension
public static IEnumerable<TDestination> MapCollection<TDestination>(
this IEnumerable collection)
{
foreach (var item in collection)
{
yield return Mapper.Map<TDestination>(item);
}
}
这是可以接受的,但是理想情况下,我想在任务扩展中删除TSource
的依赖关系,因为映射逻辑不需要它。
如果我删除TSource
,将无法使编译器同意我的意见。当我尝试使用如下定义的扩展名时:
public static async Task<IEnumerable<TDestination>> MapCollection<TDestination>(
this Task<IEnumerable> collection)
=> (await collection)
.MapCollection<TDestination>();
编译器大喊:
'
Task<IEnumerable<DataServiceModel>>
'不包含 'MapCollection
'和最佳扩展方法重载 'TaskExtensions.MapCollection<DataViewModel>(Task<IEnumerable>)
' 需要类型为“Task<IEnumerable>
”的接收者
因此,如果没有显式的泛型TSource
,我将无法识别它。我不明白问题出在哪里,因为编译器同意我的IEnumerable
扩展名,该扩展名定义为
MapCollection<TDestination>(this IEnumerable collection)
但不允许:
MapCollection<TDestination>(this Task<IEnumerable> collection)
Task
扩展名吗?Task
的用法是否存在性能问题?即线程块,死锁等。我不这么认为,但是我仍然缺乏对asnyc编程的深入了解。答案 0 :(得分:1)
您最大的问题是部分类型推断,并且无法解决
但是,如果您不介意打个电话,可以使用扩展方法和包装器类
public class Wrapper<TSource>
{
private readonly Task<IEnumerable<TSource>> _sourceCollection;
public Wrapper(Task<IEnumerable<TSource>> source)
=>_sourceCollection = source;
public async Task<IEnumerable<TDest>> To<TDest>()
=> (IEnumerable<TDest>)Mapper.Map(await _sourceCollection, _sourceCollection.GetType(), typeof(IEnumerable<TDest>));
}
public static class Extensions
{
public static Wrapper<TSource> Map<TSource>(this Task<IEnumerable<TSource>> source)
=> new Wrapper<TSource>(source);
}
用法
await service.GetAllAsync()
.Map()
.To<Something>();
注释1 :这是完全未经测试的,即使它确实起作用也缺少基本的健全性检查 < / p>
注释2 :这对于额外的异步层来说还是有点浪费的