Wpf 使用 Prism 实战开发Day13

配置 AutoMapper 关系映射

上一节ToDoController 控制器,或 IToDoService服务接口中,方法的传参都是直接传的实体类。但在实际开发过程中,这样是不允许的。标准且规范的做法是,定义一个数据传输层,即Dto层。


一.在MyToDo.Api 项目中安装 Auto Mapper


二. 在MyToDo.Shared 项目中创建一个Dtos文件夹,存放Dto文件

1. 创建 BaseDto 基类,用于存放共用属性。

cs 复制代码
    public class BaseDto
    {
        public int Id { get; set; }
    }

2. 创建待办事项 Dto类,并继承自 BaseDto 基类

cs 复制代码
    /// <summary>
    /// 待办事项数据实体
    /// </summary>
    public class ToDoDto:BaseDto
    {
        public string Title { get; set; }
        public string Content { get; set; }
        public int Status { get; set; }
    }

3.由于我们的客户端是Wpf 项目,各属性需要实现通知绑定 。所以 BaseDto类需要进行修改,并且要继承自 INotifyPropertyChanged 接口。同时还要实现一个通知绑定的方法。

cs 复制代码
    public class BaseDto:INotifyPropertyChanged
    {
        public int Id { get; set; }

        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// CallerMemberName 是一个自动获取传入名称的属性
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged([CallerMemberName] string propertyName = "")
        {
            PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
        }
    }

4.接着,要需要再修改 ToDoDto ,让它具备实现属性绑定通知功能。

cs 复制代码
  /// <summary>
  /// 待办事项数据实体
  /// </summary>
  public class ToDoDto:BaseDto
  {
      private string title;
      private string content;
      private int status;
      public string Title 
      {
          get { return title; }
          set {  title = value; OnPropertyChanged(); }
      }
      public string Content 
      {
          get { return content; }
          set { content = value; OnPropertyChanged(); }
      }
      public int Status 
      {
          get { return status; }
          set { status = value; OnPropertyChanged(); }
      }
  }

三.把实体类(ToDo)和定义的数据传输类(ToDoDto) 进行关系映射

1.在 MyToDo.Api 项目中,创建一个 Extensions 扩展文件夹。再创建一个 AutoMapperProFile 类,并且继承自 MapperConfigurationExpression,该类用于配置所有实体类和数据传输类的映射关系。

cs 复制代码
    public class AutoMapperProFile:MapperConfigurationExpression
    {
        public AutoMapperProFile()
        {
            /// 实体类和数据传输类进行映射
            CreateMap<ToDo, ToDoDto>().ReverseMap();
        }
    }
  • ReverseMap 表示两者之间可以互相进行转换。

四.修改 ToDoController 控制器传参和IToDoService 服务传参

1. IToDoService接口类传入的ToDo实体改成ToDoDto

cs 复制代码
    public interface IToDoService:IBaseService<ToDoDto>
    {

    }

2.ToDoService 服务实现类,所有传入参数是ToDo实体,需全部换成ToDoDto。并且需要在构造函数中注入 IMapper 接口。

cs 复制代码
 /// <summary>
 /// 待办事项的实现
 /// </summary>
 public class ToDoService : IToDoService
 {
     private readonly IUnitOfWork work;
     private readonly IMapper mapper;

     public ToDoService(IUnitOfWork work,IMapper mapper)
     {
         this.work = work;
         this.mapper = mapper;
     }
     public async Task<ApiResponse> AddAsync(ToDoDto model)
     {
         try
         {
             var doto= mapper.Map<ToDo>(model);//进行数据映射转换
             await work.GetRepository<ToDo>().InsertAsync(doto);
             if (await work.SaveChangesAsync() > 0) //保存成功
             {
                 return new ApiResponse(true, model); //返回true,并把添加的实体返回
             }
             return new ApiResponse("添加数据失败");
         }
         catch (Exception ex)
         {
             return new ApiResponse(ex.Message);
         }
     }

     public async Task<ApiResponse> DeleteAsync(int id)
     {
         try
         {
             var repository= work.GetRepository<ToDo>();//获取仓储
             //删除之前,先进行查询
             var todo = await repository.GetFirstOrDefaultAsync(predicate:x=>x.Id.Equals(id));
             repository.Delete(todo);
             if (await work.SaveChangesAsync() > 0) //删除成功
             {
                 return new ApiResponse(true, "删除成功"); 
             }
             return new ApiResponse("删除数据失败");
         }
         catch (Exception ex)
         {
             return new ApiResponse(ex.Message);
         }
     }

     public async Task<ApiResponse> GetAllAsync()
     {
         try
         {
            var todos= await work.GetRepository<ToDo>().GetAllAsync();
             return new ApiResponse(true, todos); //返回true,并返回所有数据
         }
         catch (Exception ex)
         {
             return new ApiResponse(ex.Message);
         }
     }

     public async Task<ApiResponse> GetSingleAsync(int id)
     {
         try
         {
            var todo= await work.GetRepository<ToDo>().GetFirstOrDefaultAsync(predicate: x => x.Id.Equals(id));
             return new ApiResponse(true, todo); //把找到的数据返回
         }
         catch (Exception ex)
         {
             return new ApiResponse(ex.Message);
         }
     }

     public async Task<ApiResponse> UpdateAsync(ToDoDto model)
     {
         try
         {
             var dbdoto = mapper.Map<ToDo>(model);
             var repository = work.GetRepository<ToDo>();//获取仓储
             //更新之前,先拿到要更新的数据
             var todo = await repository.GetFirstOrDefaultAsync(predicate: x => x.Id.Equals(dbdoto.Id));
             todo.Title = dbdoto.Title;
             todo.Content = dbdoto.Content;
             todo.Status = dbdoto.Status;
             todo.UpdateDate = DateTime.Now;
             repository.Update(todo);
             if (await work.SaveChangesAsync() > 0) //更新成功
             {
                 return new ApiResponse(true, "更新成功");
             }
             return new ApiResponse("更新数据失败");
         }
         catch (Exception ex)
         {
             return new ApiResponse(ex.Message);
         }
     }
 }
  • IMapper 接口里的 Map 方法,用于 Dto和实体类之间的数据映射转换

3.把ToDoController 控制器传入的ToDo实体改成ToDoDto

cs 复制代码
 [ApiController]
 [Route("api/[controller]/[action]")]
 public class ToDoController:ControllerBase
 {
     private readonly IToDoService service;

     public ToDoController(IToDoService service)
     {
         this.service = service;
     }

     [HttpGet]
     public async Task<ApiResponse> Get(int id)=> await service.GetSingleAsync(id);

     [HttpGet]
     public async Task<ApiResponse> GetAll() => await service.GetAllAsync();

     [HttpPost]
     public async Task<ApiResponse> Add([FromBody]ToDoDto model) => await service.AddAsync(model);

     [HttpPost]
     public async Task<ApiResponse> Update([FromBody] ToDoDto model) => await service.UpdateAsync(model);

     [HttpDelete]
     public async Task<ApiResponse> Delete(int id) => await service.DeleteAsync(id);
 }

五.最后,需要在Program.cs 中,进行注册 AutoMapper 服务

cs 复制代码
//注入AutoMapper
builder.Services.AddSingleton(new MapperConfiguration(config =>
{
    config.AddProfile(new AutoMapperProFile());
}).CreateMapper());

六.运行测试接口都正常,证明配置AutoMapper 成功了

相关推荐
就是有点傻3 小时前
WPF中Prism框架的简单使用
wpf
界面开发小八哥4 小时前
界面控件DevExpress WPF中文教程:TreeList视图及创建分配视图
.net·wpf·界面控件·devexpress·ui开发
月落.6 小时前
WPF Prism中的区域(Region)管理
wpf·prism
Envyᥫᩣ6 小时前
深入浅出C#编程语言
开发语言·c#
机器人天才一号9 小时前
C#从入门到放弃
开发语言·c#
吾与谁归in9 小时前
【C#设计模式(10)——装饰器模式(Decorator Pattern)】
设计模式·c#·装饰器模式
冷眼Σ(-᷅_-᷄๑)15 小时前
Path.Combine容易被忽略的细节
c#·.net
SongYuLong的博客21 小时前
C# (定时器、线程)
开发语言·c#
百锦再1 天前
详解基于C#开发Windows API的SendMessage方法的鼠标键盘消息发送
windows·c#·计算机外设
无敌最俊朗@1 天前
unity3d————协程原理讲解
开发语言·学习·unity·c#·游戏引擎