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

4 篇文章 1 订阅
4 篇文章 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);//插入代码上的注释放入Swagger
                options.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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NumPy是在python中处理数据的最基本和最强大的包。 如果您打算从事数据分析或机器学习项目,那么对numpy的充分理解几乎是必须的。 其他用于数据分析的软件包(如pandas)是建立在numpy之上,用于构建机器学习应用的scikit-learn软件包也在numpy上运行。 但对于.NET开发人员来说,却没有这样的强大工具库。 虽然有像Deedle和Math.NET这样的开源库,但它们不是很容易使用,也不能借用很多现有的python代码。 NumSharp(Numerical .NET)可以说是C#中的线性代数库。 它是用C#编写的,符合.netstandard 2.0库标准。 它的目标是让.NET开发人员使用NumPy的语法编写机器学习代码,从而最大限度地借鉴现有大量在python代码的转译成本。 NumSharp使用最新的Span技术安全高效地访问内存,优化每个模拟API的性能,确保最底层的NDArray达到最佳性能状态。NumSharp对于在数组上执行数学和逻辑运算非常有用。 它为.NET中的n阵列和矩阵的操作提供了大量有用的功能。 让我们给出一个代码片段来说明如何使用NumSharp。 // 初始化一个NumSharp实例,类名故意叫NumPy var np = new NumPy(); // 产生一个数字0到9的向量 np.arange(10) // 产生一个3维张量 np.arange(12).reshape(2, 3, 2); // 产生10个0到9的随机数,并转换成5*5的矩阵 np.random.randint(low: 0, high: 10, size: new Shape(5, 5)); 上面的代码是不是看起来否非常接近python代码?简直就是如出一辙。NumSharp的目的就是让你可以轻松的复制粘贴Python代码。 如何安装: PM> Install-Package NumSharp   NumSharp 已被如下项目使用: Pandas.NET Bigtree.MachineLearning CherubNLP BotSharp 标签:numpy

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值