当前位置: 代码迷 >> 综合 >> 【二】Asp.Netcore使用Panda.DynamicWebApi来进行Controller解耦@Asp.netcore Code First +DDD学习笔记
  详细解决方案

【二】Asp.Netcore使用Panda.DynamicWebApi来进行Controller解耦@Asp.netcore Code First +DDD学习笔记

热度:98   发布时间:2023-12-26 19:07:45.0

在Asp.Netcore内Panda.DynamicWebApi的使用方法,以及如何使用Panda.DynamicWebApi来使Controller何Server解耦

 

主题:Asp.netcore Code First +DDD学习笔记

目录:

   【一】 CodeFirst+DDD项目结构的构建

   【二】Asp.Netcore使用Panda.DynamicWebApi来进行Controller解耦

   【三】Asp.NetCore使用Efcore+Mysql实现CodeFirst

   【四】EfCore实现全自动化迁移

     案例代码下载点击

   当我们把Controller单独建成一个项目来解耦Controller后,Api那边进行了引用,发现接口并没有生成,但是我们需要接口生成。通过Abp我们知道了需要动态生成接口,于是找到了一个动态生成接口的组件:Panda.DynamicWebApi。

 引用官方的一段话

Panda.DynamicWebApi 是一个动态生成WebApi的组件,生成的API符合Restful风格,受启发于ABP。它可以根据符合条件的类来生成WebApi,由MVC框架直接调用逻辑,无性能问题,完美兼容Swagger来构建API说明文档,与手动编写Controller相比并无区别。

应用场景:DDD架构中的应用逻辑层,可使用本组件来直接生成WebApi,而无需再用Controller来调用。

git地址:https://github.com/dotnetauth/Panda.DynamicWebApi/blob/master/README_zh-CN.md

【二】Controller使用Panda.DynamicWebApi

1、首先理解Panda.DynamicWebApi组件动态生成webApi的机制。

(1)要让类生成动态API需要满足两个条件,一个是该类直接间接实现 IDynamicWebApi,同时该类本身或者父抽象类或者实现的接口具有特性 DynamicWebApi

(2)添加特性 [NonDynamicWebApi] 可使一个类或者一个方法不生成API,[NonDynamicWebApi] 具有最高的优先级

   更多机制请看git源码那里的第二步有详细介绍

2、开始载入组件

(1)在Api项目上管理Nuget包里面搜索并安装Panda.DynamicWebApi和Swashbuckle.AspNetCore(该组件时swagger组件),给Controller项目上安装Panda.DynamicWebApi,如图所示:

 (2)在Api项目上注入该组件。

          删除Api上面的Controller文件夹,使Api项目如下图所示 

            

         在Startup文件里的ConfigureServices方法下添加如下代码

          

           //动态生成Api接口services.AddDynamicWebApi();//配置SwaggerApi自动生成器services.AddSwaggerGen(options =>{options.DocInclusionPredicate((docName, description) => true);//swagger支持动态生成的api接口options.CustomSchemaIds(type => type.FullName);               //swagger支持动态生成的api接口options.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });var basePath = Path.GetDirectoryName(typeof(Program).Assembly.Location);//获取代码运行的相对路径options.IncludeXmlComments(Path.Combine(basePath, "Api.xml"), true);//插入代码上的注释放入Swaggeroptions.IncludeXmlComments(Path.Combine(basePath, "ApiController.xml"), true);});

        在Startup文件里的Configure方法下添加如下代码

           //使用SwaggerApi自动生成器app.UseSwagger();//使用SwaggerApi自动生成器的Ui界面app.UseSwaggerUI(option =>{option.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");});

       这样添加完成后,由于之前Api项目引用了Controller项目,只要Controller项目里面满足Panda.DynamicWebApi的接口生成机制(直接间接实现 IDynamicWebApi+具有DynamicWebApi特性)就会自动生成接口,并且会在swagger(不了解Swagger的可以点击来进行详细了解)上显示出来,如下:

     在Controller项目添加一个TestController的测试类

   

  代码如下:

using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes;namespace Controller
{[DynamicWebApi]public class TestController : IDynamicWebApi{public string GetHelloWorld(){return "Hello World !!";}}
}

  启动Api项目,将会在Swagger上看到该接口,如图:

   (3)在上面的这些步骤,我们完成Controller的解耦,Controller的代码可以写在别的项目了,而主项目只需要添加对该项目的引用即可,在为了方便,我们不能每个接口都去实现IDynamicWebApi标记DynamicWebApi特性,所以我们需要添加一个公共接口来继承和标记该特性,这样别的方法只需要继承即可。同理我们也可能需要每个接口都要有的一些通用的方法,所以我这里还写了一个Api的基类。

 给Controller项目下添加一个Core(存放基类和通用方法的)的文件夹和一个Controllers(存放接口使用的)的文件夹如下所示:

注:这里的ApiController.xml是在swagger教程里面生成注释文件教程里面自动生成的。具体如何配置生成的请点击。这个注释文件一定要在Controller上配置,这样生成的swaggerApi文档才会有我们写的注释。

   在Core里面添加一个IAppService接口文件和一个AppService类文件 如图所示:

这里面我扩展了两个在DDD里面比较通用的方法,本来打算用AutoMapper的,由于测试就没去用了,做Domain和Dto之间的映射还是AutoMapper好点(有个缺点是第一次映射还没我下面写的运行速度快,但是多次映射的话AutoMapper的性能还可以)

IAppService的代码如下

using Panda.DynamicWebApi;
using Panda.DynamicWebApi.Attributes;
using System.Collections.Generic;namespace Controller.Core
{[DynamicWebApi]public interface IAppService : IDynamicWebApi{/// <summary>/// 传入实体内容,转化为对应的Dto/// </summary>/// <typeparam name="TDto">要转化的Dto类</typeparam>/// <param name="entity">传入的实体数据</param>/// <returns></returns>TDto EntityToDto<TDto>(object entity) where TDto : class, new();/// <summary>/// 传入List实体内容,转化为对应的List Dto/// </summary>/// <typeparam name="TDto"></typeparam>/// <param name="entityList">传入的List实体数据</param>/// <returns></returns>List<TDto> EntityToDto<TDto>(List<object> entityList) where TDto : class, new();}
}

AppService的代码如下

using AutoMapper;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;namespace Controller.Core
{public class AppService : IAppService{public AppService(){}/// <summary>/// 传入实体内容,转化为对应的Dto/// </summary>/// <typeparam name="TDto">要转化的Dto类</typeparam>/// <param name="entity">传入的实体数据</param>/// <returns></returns>public TDto EntityToDto<TDto>(object entity) where TDto : class, new(){return Entitytodto<TDto>(entity);}/// <summary>/// 传入List实体内容,转化为对应的List Dto/// </summary>/// <typeparam name="TDto"></typeparam>/// <param name="entityList">传入的List实体数据</param>/// <returns></returns>public List<TDto> EntityToDto<TDto>(List<object> entityList) where TDto : class, new(){List<TDto> list = new List<TDto>();foreach (var childObject in entityList){list.Add(Entitytodto<TDto>(childObject));}return list;}/// <summary>/// 传入实体内容,转化为对应的Dto/// </summary>/// <typeparam name="TDto"></typeparam>/// <param name="entity"></param>/// <returns></returns>private TDto Entitytodto<TDto>(object entity) where TDto : class, new(){TDto dto = new TDto();PropertyInfo[] propertyInfos = entity.GetType().GetProperties();PropertyInfo[] dtoproperty = dto.GetType().GetProperties();for (int i = 0; i < propertyInfos.Length; i++){for (int j = 0; j < dtoproperty.Length; j++){if (propertyInfos[i].Name == dtoproperty[j].Name){dtoproperty[j].SetValue(dto, propertyInfos[i].GetValue(entity));break;}}}return dto;}}
}

之后我们把TestController类移动到Controllers文件夹下 如图:

并修改代码(这里不需要实现IDynamicWebApi标记DynamicWebApi特性只需要继承我们自己的AppService, IAppService)如下:

using Controller.Core;namespace Controller.Controllers.Test
{/// <summary>/// 测试类/// </summary>public class TestAppService : AppService, IAppService{public string GetHelloWorld(){return "Hello World !!";}}
}

再次运行Api项目你可以看到Swagger上Test接口还是在的,如下:

到这里Controller从API里解耦出来已经初步经完成。

github地址:https://github.com/houliren/Asp.netcore-Code-First-DDD

  相关解决方案