博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
构建应用层服务
阅读量:4931 次
发布时间:2019-06-11

本文共 4622 字,大约阅读时间需要 15 分钟。


今天谈谈《构建应用层服务》。

理论学习:

应用服务提供了一些门面样式方法来分离表现层和领域层。这样做的目的也是为了解耦,以后表现层就不用直接和业务逻辑层(核心层)打交道了,而是通过应用服务层(相当于媒介)来处理。应用服务层不仅定义了很多服务方法供表现层直接调用,而且还提供了一些Dtos(Data Transfer Object)。

说到Dto,好处确实挺多的。

第一,可以将它理解为一个简化的实体,更方便。比如,我们有一个User表,里面有Id,Name,Password,IsDeleted,CreationTime等等。那么我们简化的UserDto对象就只含有Name和IsDeleted两个字段就够用了,因为表现层就只用到了这两个字段。

第二,更安全,性能更好。如果不用Dto而用实体类的话,最后生成的查询就会将实体的所有字段都会查询出来。这样一来就暴露了一些重要的数据给一些我们不想这些数据被看到的人。

第三,应用扩展性更好,耦合度降低。表现层是通过一个Dto对象作为参数来调用应用服务方法的,然后使用领域对象(实体类对象)执行特定的业务逻辑并返回一个Dto对象给表现层,所以,表现层完全独立于领域层。在一个理想的应用中,表现层和领域层不会直接打交道。

第四,序列化问题。当返回一个数据对象到表现层时,很可能会在某个地方序列化。比如,在一个返回JSON的MVC方法中,你的对象可能会被序列化成Json发送到客户端。如果返回一个实体的话会有问题的。比如,这个User实体有一个Role的应用,如果要序列化User的话也会序列化Role。甚至Role可能有List<Permission>,Permission又有一个PermissionGroup的引用等等…你敢想象序列化之后的对象吗?亦可以轻易地一下子序列化整个数据库。所以,在这种情况下返回一个安全序列化的、特别设计的DTOs是一个好的做法。

先来定义Dtos,看下面代码:

namespace Noah.ChargeStation.Application.CitiesApp.Dto{    public class CityInput : IInputDto    {        public string Name { get; set; }        public string Code { get; set; }        public string ProvinceCode { get; set; }    }    public class GetCityInput : IInputDto    {        public string Name { get; set; }        public string ProvinceCode { get; set; }    }    public class CreateCityInput : IInputDto, IShouldNormalize    {        [Required]        public string Name { get; set; }        [Required]        public string Code { get; set; }        [Required]        public string ProvinceCode { get; set; }        public DateTime UpdatedTime { get; set; }        public string UpdatedBy { get; set; }        public void Normalize()        {            if (UpdatedTime==null)            {                UpdatedTime=DateTime.Now;            }        }    }}

这个是输入方向的Dto,实现了IInputDto接口,这样的话ABP可以自动帮助我们进行数据校验。当然,我们也可以添加数据注解进行校验。校验之后,还可以实现IShouldNormalize接口来设置缺省值。

namespace Noah.ChargeStation.Application.CitiesApp.Dto{    public class CityOutput:IOutputDto    {        public string Code { get; set; }        public string Name { get; set; }        public string ProvinceCode { get; set; }    }    public class GetCitiesOutput:IOutputDto    {        public List
Cities { get; set; } }}

以上是输出方向的Dto。

 

接下来我定义一个城市表的服务接口ICityAppService,我的命名规范是”I+实体类单数+AppService”。

namespace Noah.ChargeStation.Application.CitiesApp{    public interface ICityAppService:IApplicationService    {        GetCitiesOutput GetCities(GetCityInput input);        Task
GetCitiesAsync(GetCityInput input); void UpdateCity(CityInput input); Task UpdateCityAsync(CityInput input); void CreateCity(CityInput input); Task CreateCityAsync(CityInput input); }}

以上定义的方法有同步和异步两个版本。

接下来实现应用服务接口,这里只实现一个方法GetCities(…),望读者举一反三。

public class CityAppService : ChargeStationAppServiceBase, ICityAppService    {        private readonly IRepository
_cityRepository; public CityAppService(IRepository
cityRepository) { _cityRepository = cityRepository; } public GetCitiesOutput GetCities(GetCityInput input) { //根据不同条件进行查询不同的结果 //Mapper.CreateMap
(); //根据城市名称查询城市数据 if (!string.IsNullOrEmpty(input.Name)) { var cityEntity = _cityRepository.GetAllList(c => c.Name == input.Name).FirstOrDefault(); return new GetCitiesOutput() { CityDto = Mapper.Map
(cityEntity) }; } //根据省份编码查询城市数据 if (!string.IsNullOrEmpty(input.ProvinceCode)) { var cityEntityList = _cityRepository.GetAllList(c => c.ProvinceCode == input.ProvinceCode); return new GetCitiesOutput() { CityDtoList = Mapper.Map
>(cityEntityList) }; } return null; } public void UpdateCity(CityInput input) { Logger.Info("Updating a City for input: " + input); } public void CreateCity(CityInput input) { //var city = _cityRepository.FirstOrDefault(c => c.Name == input.Name); //if (city != null) //{ // throw new UserFriendlyException("该城市数据已经存在!"); //} //city = new City() { Code = input.Code, Name = input.Name, ProvinceCode = input.ProvinceCode }; //_cityRepository.Insert(city); } public Task
GetCitiesAsync(GetCityInput input) { throw new System.NotImplementedException(); } public Task UpdateCityAsync(CityInput input) { throw new System.NotImplementedException(); } public Task CreateCityAsync(CityInput input) { throw new System.NotImplementedException(); } }

这里又出现了个新东西AutoMapper,关于这个的使用,我这几天会专门开一个关于AutoMapper的专题,敬请期待。代码没有难度,也就不多做解释了。今天就到这里吧。下次再讲。

转载于:https://www.cnblogs.com/farb/p/4930968.html

你可能感兴趣的文章
Android透明无边框圆形进度条之最简单实现
查看>>
Dynamics CRM2016 Web API之Expand related entities & $ref & $count
查看>>
MEF 编程指南(八):过滤目录
查看>>
css样式中position和_position的区别
查看>>
hdu 3065 病毒侵袭持续中 AC自动机
查看>>
ajax返回json数据示例
查看>>
DAY9 函数初识(各种参数的用法)
查看>>
9-19练习
查看>>
【zz】贝叶斯推断及其互联网应用
查看>>
看看我做的一款 时间轴 插件 timegliderJs
查看>>
哈希表的构造方法
查看>>
设计包含min函数的栈
查看>>
在Outlook中用VBA导出HTML格式邮件
查看>>
BeanUtils String转Date注册器
查看>>
获得进程/线程已经被分配的所有cpu时间片的总和
查看>>
spark-submit常用参数
查看>>
【西北师大-19软工】第十三、十四次作业汇总暨期末总结
查看>>
游戏应该是怎样的
查看>>
Java多线程性能优化
查看>>
嵌入式开发入门(4)—驱动入门之时序图分析【20121211修改,未完】
查看>>