繁体   English   中英

带有泛型和AutoMapper的.NET Core API操作

[英].NET Core API action with generics and AutoMapper

我正在构建一个ASP.NET Core API。 我有一个动作,我希望在一组控制器上基本相同。 因此,我创建了那些控制器从其继承的EntityController ,如下所示。

注意:在下面两个类中使用的省略号表示更多的操作及其相关服务,遵循为简单起见而省略的相同模式。

public class EntityController : BaseController
{
    protected readonly SeedService SeedService;

    protected EntityController(IMemoryCache memoryCache, SeedService seedService) : base(memoryCache)
    {
        SeedService = seedService;
    }

    [HttpGet]
    public async Task<IActionResult> Seed()
    {
        var controllerName = ControllerContext.RouteData.Values["controller"].ToString();
        return await GetSeed(controllerName);
    }

    private async Task<IActionResult> GetSeed(string controllerName)
    {
        switch (controllerName)
        {
            case "lists":
                return await MemoryCache.GetOrCreateAsync(CacheKeys.Entry, async entry =>
                {
                    entry.SlidingExpiration = TimeSpan.FromSeconds(3);
                    return Json(await SeedService.GetAllFilterLists());
                });
            case "languages":
                return await MemoryCache.GetOrCreateAsync(CacheKeys.Entry, async entry =>
                {
                    entry.SlidingExpiration = TimeSpan.FromSeconds(3);
                    return Json(await SeedService.GetAllLanguages());
                });
            ...
            default:
                return await Task.FromResult(NotFound());
        }
    }
}

以下是这些操作调用的服务方法:

public class SeedService
{
    private readonly FilterListsDbContext filterListsDbContext;

    public SeedService(FilterListsDbContext filterListsDbContext)
    {
        this.filterListsDbContext = filterListsDbContext;
    }

    public async Task<IEnumerable<FilterListSeedDto>> GetAllFilterLists()
    {
        return await filterListsDbContext.Set<FilterList>().ProjectTo<FilterListSeedDto>().ToListAsync();
    }

    public async Task<IEnumerable<LanguageSeedDto>> GetAllLanguages()
    {
        return await filterListsDbContext.Set<Language>().ProjectTo<LanguageSeedDto>().ToListAsync();
    }

    ...
}

如何使用泛型(或替代方法)减少复制/粘贴重复? 我试图用类似一个Dictionary<string, Type>查找的Type从控制器名称动态,但我不知道是怎么产生的GetAll<T>()的方法SeedService会看? 下面的方法无效,因为该方法取决于AutoMapper投影的实体和DTO模型的类型。

public async Task<IEnumerable<T>> GetAll<T>()
{
    return await filterListsDbContext.Set<T>().ProjectTo<T>().ToListAsync();
}

您可以轻松地将所有样板代码删除为一个通用方法:

public async Task<IEnumerable<TResult>> GetAll<TEntry, TResult>() where TEntry : class
{
    return await filterListsDbContext.Set<TEntry>()
        .ProjectTo<TResult>()
        .ToListAsync();
}

由于返回的是IEnumerable ,因此您可能需要更改为.ToArrayAsync() 另外,由于要投影到非实体,因此上下文不会接受更改,因此可以进一步添加.AsNoTracking()以避免将实体添加到上下文:

public async Task<IEnumerable<TResult>> GetAll<TEntry, TResult>() where TEntry : class
{
    return await filterListsDbContext.Set<TEntry>()
        .AsNoTracking()
        .ProjectTo<TResult>()
        .ToArrayAsync();
}

正如我在评论中提到的,您可以将其放在基本控制器中,然后执行以下操作:

public class BaseController<TEntity, TViewModel>
{    
    public async Task<IEnumerable<TViewModel>> GetAll()
    {
        return await filterListsDbContext.Set<TEntity>()
            .AsNoTracking()
            .ProjectTo<TViewModel>()
            .ToArrayAsync();
    }
}

public class LanguageController : BaseController<Language, LanguageSeedDto>
{
    (in some action)
    var data = await GetAll();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM