这一讲,我们要创建应用层,让客户端与应用层进行交互。
创建ZL.Poem.Application
在我们的解决方案中增加一个.Net Core类库项目,命名为ZL.Poem.Application。 在解决方案资源管理器中选择该项目的依赖项,在右键菜单中选择添加引用,将ZL.Poem.Core添加为依赖项目。
由于我们需要使用DTO对实体的映射,因此需要在NuGet中增加Abp.AutoMapper。还需要将ZL.Poem.Core添加到项目的依赖项中。
与前面的步骤一样,还是先增加一个Abp的模块,命名为PoemApplicationModule:
using Abp.AutoMapper;
using Abp.Modules;
using System.Reflection;
using ZL.Poem.Core;
namespace ZL.Poem.Application
{
[DependsOn(typeof(PoemCoreModule), typeof(AbpAutoMapperModule))]
public class PoemApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
}
这里设置了模块的依赖关系,这个模块依赖PoemCoreModule和AbpAutoMapperModule。
创建DTO
然后创建一个目录,命名为Poems,在这个目录里我们创建有关Poem的基础服务,比如关于诗和诗人的查询,以及分类管理。首先我们创建一个诗人的DTO,命名为PoetDto:
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using ZL.Poem.Core.Poems;
namespace ZL.Poem.Application.Poems
{
[AutoMapFrom(typeof(Poet))]
public class PoetDto : EntityDto
{
public string Name { get; set; }
public string Description { get; set; }
}
}
DTO需要与实体进行转换,如果都在代码中完成,会产生大量的相似的转换代码。Abp采用AutoMap实现DTO到实体的映射。
接下来定义一个输入参数DTO,PagedResultRequestDto,这个dto实现IPagedResultRequest接口,负责分页查询的参数传入:
using Abp.Application.Services.Dto;
namespace ZL.Poem.Application.Poems
{
/// <summary>
/// 分页查询传入参数
/// </summary>
public class PagedResultRequestDto : IPagedResultRequest
{
/// <summary>
/// 跳过的记录数
/// </summary>
public int SkipCount { get; set; }
/// <summary>
/// 返回的最大记录数
/// </summary>
public int MaxResultCount { get; set; }
}
}
创建服务
接下来,创建服务接口如下:
using Abp.Application.Services;
using Abp.Application.Services.Dto;
namespace ZL.Poem.Application.Poems
{
public interface IPoemAppService : IApplicationService
{
/// <summary>
/// 获取诗人分页
/// </summary>
/// <param name="dto"></param>
/// <returns></returns>
PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto);
}
}
这里先只定义了一个函数,用于获取诗人的分页数据。返回的结果是Abp定义的PageResultDto<T>。
这个接口的实现如下:
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using System.Collections.Generic;
using System.Linq;
using ZL.Poem.Core.Poems;
namespace ZL.Poem.Application.Poems
{
public class PoemAppService : ApplicationService, IPoemAppService
{
private readonly IRepository<Core.Poems.Poem> _poemRepository;
private readonly IRepository<Category> _categoryRepository;
private readonly IRepository<Poet> _poetRepository;
private readonly IRepository<CategoryPoem> _categoryPoemRepository;
public PoemAppService(IRepository<Core.Poems.Poem> poemRepository
, IRepository<Category> categoryRepository
, IRepository<Poet> poetRepository
, IRepository<CategoryPoem> categoryPoemRepository)
{
_poemRepository = poemRepository;
_categoryRepository = categoryRepository;
_poetRepository = poetRepository;
_categoryPoemRepository = categoryPoemRepository;
}
public PagedResultDto<PoetDto> GetPagedPoets(PagedResultRequestDto dto)
{
var count = _poetRepository.Count();
var lst = _poetRepository.GetAll().OrderBy(o => o.Id).PageBy(dto).ToList();
return new PagedResultDto<PoetDto>
{
TotalCount = count,
Items = lst.MapTo<List<PoetDto>>()
};
}
}
}
这里定义了Poem、Category和Poet的仓储对象,目前只用到Poet的仓储对象。在GetPagedPoets中,首先获取总数,然后获取分页集合。这里获取的结果是Poet的集合,使用MapTo转换为DTO集合。
修改客户端,调用应用层
下面我们修改客户端,调用应用层。
首先,在ZL.Game.ConsoleClient中增加对项目ZL.Poem.Application的引用。
然后,修改模块的依赖关系:
using Abp.Modules;
using System.Reflection;
using ZL.Poem.Application;
using ZL.Poem.EF;
namespace ZL.Poem.ConsoleClient
{
[DependsOn(typeof(PoemDataModule),
typeof(PoemApplicationModule))]
public class PoemConsoleClientModule : AbpModule
{
public override void PreInitialize()
{
Configuration.DefaultNameOrConnectionString = "Server=localhost; Database=PoemNew; Trusted_Connection=True;";
}
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
}
将对PoemCoreModule的依赖改为PoemApplicationModule。
接下来,修改Service类,用来访问应用层:
using Abp.Dependency;
using System;
using ZL.Poem.Application.Poems;
namespace ZL.Poem.ConsoleClient
{
public class Service : ITransientDependency
{
private IPoemAppService _appService;
public Service(IPoemAppService appService)
{
_appService = appService;
}
public void Run()
{
var res = _appService.GetPagedPoets(new PagedResultRequestDto { MaxResultCount = 10, SkipCount = 0 });
Console.WriteLine(res.TotalCount);
foreach (var poet in res.Items)
{
Console.WriteLine(poet.Name);
}
}
}
}
从代码中可以看到,Abp将PoemAppService被注入到Service中,不需要我们进行实例化操作。
这里获取前10个诗人,输入诗人的总数和前10个诗人的名字。
在main函数中调用Service:
using Abp;
using Abp.Dependency;
using System;
namespace PoemGame.ConsoleClient
{
class Program
{
static void Main(string[] args)
{
using (var bootstrapper = AbpBootstrapper.Create<PoemGameModule>())
{
//初始化模块
bootstrapper.Initialize();
var service = IocManager.Instance.Resolve<Service>();
service.Run();
Console.WriteLine("Press enter to exit...");
Console.ReadLine();
}
}
}
}
运行结果如下:
下一步工作
下一步我们需要创建单元测试,并使用单元测试对应用层进行测试。
本文同步发布在我的个人网站 http://www.jiagoushi.cn