从零开始学习ABP vNext开发 (六)创建应用层
现在我们来创建应用层,这样客户端只与应用层打交道就可以了。
与前面创建领域层模块和数据访问EF模块一样,我们在解决方案中增加.Net Core类库项目,作为服务层模块,将项目命名为ZL.AbpNext.Poem.Application,我们需要使用Nuget管理器,为项目增加必要的依赖项,如下:

图片.png
然后,增加一个Abp模块,名称为PoemApplicationModule,这个模块依赖于PoemCoreModule。
接下来,创建一个目录Poems,在这个目录中增加一个Dto类PoetDto:
namespace ZL.AbpNext.Poem.Application.Poems
{
public class PoetDto:EntityDto<int>
{
public string Name { get; set; }
public string Description { get; set; }
}
}
DTO的目的是隔离客户端与领域模型,但很多情况下,DTO与领域模型基本上是相同的,ABP使用AutoMapper实现DTO到领域实体的映射。这需要创建一个映射Profile:
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.Application.Poems
{
public class PoemAppAutoMapperProfile : Profile
{
public PoemAppAutoMapperProfile()
{
CreateMap<Poet, PoetDto>();
}
}
}
还需要在模块中进行声明:
using System;
using Volo.Abp.AutoMapper;
using Volo.Abp.Modularity;
using ZL.AbpNext.Poem.Application.Poems;
using ZL.AbpNext.Poem.Core;
namespace ZL.AbpNext.Poem.Application
{
[DependsOn(
typeof(PoemCoreModule),
typeof(AbpAutoMapperModule))]
public class PoemApplicationModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddProfile<PoemAppAutoMapperProfile>(validate: true);
});
}
}
}
现在创建IPoemAppService接口:
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
namespace ZL.AbpNext.Poem.Application.Poems
{
public interface IPoemAppService:IApplicationService
{
/// <summary>
/// 获取诗人分页
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto);
}
}
我们先只增加一个函数,获取分页的诗人。然后我们创建PoemAppService:
using System.Collections.Generic;
using System.Linq;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.Application.Poems
{
public class PoemAppService : ApplicationService, IPoemAppService
{
private readonly IRepository<Poet> _poetRepository;
public PoemAppService(IRepository<Poet> poetRepository)
{
_poetRepository = poetRepository;
}
public PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto)
{
using (var uow = UnitOfWorkManager.Begin(new AbpUnitOfWorkOptions()))
{
var count = _poetRepository.Count();
var lst = _poetRepository.OrderBy(o => o.Id).PageBy(dto).ToList();
var items = new List<PoetDto>();
return new PagedResultDto<PoetDto>
{
TotalCount = count,
Items = ObjectMapper.Map<List<Poet>, List<PoetDto>>(lst)
};
}
}
}
}
到这里,应用层编写完成,下面使用Client调用应用层。
首先,在PoemConsoleClientModule中增加PoemApplicationModule依赖:
using Volo.Abp.Autofac;
using Volo.Abp.Modularity;
using ZL.AbpNext.Poem.Application;
using ZL.AbpNext.Poem.Core;
using ZL.AbpNext.Poem.EF;
namespace ZL.AbpNext.Poem.ConsoleClient
{
[DependsOn(
typeof(AbpAutofacModule),
typeof(PoemCoreModule),
typeof(PoemApplicationModule),
typeof(PoemDataModule))]
public class PoemConsoleClientModule:AbpModule
{
}
}
然后,改造Service,使用服务层访问数据:
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using ZL.AbpNext.Poem.Application.Poems;
using ZL.AbpNext.Poem.Core.Poems;
namespace ZL.AbpNext.Poem.ConsoleClient
{
public class Service : ITransientDependency
{
//IRepository<Poet> repository;
//IUnitOfWorkManager uowManager;
IPoemAppService appService;
//public Service(IRepository<Poet> repository, IUnitOfWorkManager uowManager)
//{
// this.repository = repository;
// this.uowManager = uowManager;
//}
public Service(IPoemAppService appService)
{
this.appService = appService;
}
public void Run()
{
//Console.WriteLine("你好");
//using (var uow = uowManager.Begin(new AbpUnitOfWorkOptions()))
//{
// //获取第一个诗人
// //var poet = repository.FirstOrDefault();
// var poet = repository.AsQueryable().Include(p => p.Poems).FirstOrDefault();
// Console.WriteLine(poet.Name);
// Console.WriteLine(poet.Poems.Count());
// Console.WriteLine(poet.Poems.ToList()[0].Author.Name);
//}
var res=appService.GetPagedPoets(new Volo.Abp.Application.Dtos.PagedResultRequestDto { MaxResultCount = 10, SkipCount = 0 });
Console.WriteLine(res.TotalCount);
foreach(var dto in res.Items)
{
Console.WriteLine(dto.Name);
}
}
}
}
运行如下:

图片.png
作者:寻找无名的特质
链接:https://www.jianshu.com/p/610c9b8b3ecf
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)