.Net Core——用代码写代码?

news2024/12/22 19:06:45

想要用代码写代码,肯定是绕不开反射的。反射的概念相比都不陌生,只是应用多少就因人而异,今天分享一个代码生成器的思路,仅供参考,不要过分依赖哦。

思路分析

众所周知,利用反射可以在程序运行时获取到任一对象的类型、属性、参数、方法等,并加以调用,利用这些获取到的可以在程序运行时追加各种自定义的功能。以CRUD为例,我们可以利用反射获取到所有的Model并编写代码模板,最终达成用代码生成代码的结果。思路既然能走通,开搞开搞~

编码阶段

首先要确定生成哪些代码。CRUD每天都在做,但大部分都一样,这就导致每天有些时间都在板砖,毫无意义。所以我们需要自动生成全库的CRUD代码。

首先要写一个CRUD的模板代码,考虑到ORM框架太多,这里就以SqlSugar为例:

     [HttpGet]
        public async Task<IActionResult> GetList(int index = 1, int size = 15)
        {
            RefAsync<int> count = 0;

            return PageMsg(await _sqlHelper.DB
                .Queryable<Models.AD>()
                .OrderBy(x => x.Weight)
                .ToPageListAsync(index, size, count), count.Value);
        }

        [HttpPost, Role("添加广告")]
        public async Task<IActionResult> Add([FromForm] Models.AD ad)
        {
            Models.AD add = await _sqlHelper.DB
                .Insertable(ad)
                .RemoveDataCache()
                .ExecuteReturnEntityAsync();

            return Ok(add);
        }

        [HttpPut, Role("修改广告")]
        public async Task<IActionResult> Cag([FromForm] Models.AD ad)
        {
       int result = await _sqlHelper.DB
                .Updateable(ad)
                .RemoveDataCache()
                .ExecuteCommandAsync();
        
        return YesOrNo(result > 0);
        }

        [HttpDelete]
        public async Task<IActionResult> Delete([FromForm] int id)
        {
        int result = await _sqlHelper.DB
                .Deleteable<Models.AD>()
                .Where(x => x.ID == id)
                .ExecuteCommandAsync();

        return YesOrNo(result > 0);
        }

能看出这是一组操作AD类的CRUD,接下来就是需要把上面的模板封装起来,AD这种表的名称作为变量输入即可,如果想控制代码文件的路径,也可以作为参数传入。完整版:

     public void Make(string tableName, string path)
        {
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);

            using FileStream fs = new FileStream($"{path}/{tableName}Controller.cs", FileMode.Append);

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append("using System.Threading.Tasks;");
            sb.Append("\n");
            sb.Append("using XXXX.Services.DB;");
            sb.Append("\n");
            sb.Append("using Microsoft.AspNetCore.Authorization;");
            sb.Append("\n");
            sb.Append("using Microsoft.AspNetCore.Mvc;");
            sb.Append("\n");
            sb.Append("using SqlSugar;");
            sb.Append("\n");
            sb.Append("namespace XXXX.Controllers.v1");
            sb.Append("\n");
            sb.Append("{");
            sb.Append("\n");
            sb.Append("     [ApiController, Route(\"v1/[controller]/[action]\"), Authorize]");
            sb.Append("\n");
            sb.Append($"     public class {tableName}Controller : BaseController");
            sb.Append("\n");
            sb.Append("     {");
            sb.Append("\n");
            sb.Append("         private readonly SqlHelper _sqlHelper;");
            sb.Append("\n");
            sb.Append($"        public {tableName}Controller(SqlHelper sqlHelper)");
            sb.Append("\n");
            sb.Append("         {");
            sb.Append("\n");
            sb.Append("             _sqlHelper = sqlHelper;");
            sb.Append("\n");
            sb.Append("         }");
            sb.Append("\n");
            sb.Append("         [HttpGet]");
            sb.Append("\n");
            sb.Append($"         public async Task<IActionResult> GetList(int index = 1, int size = 15)");
            sb.Append("\n");
            sb.Append("         {");
            sb.Append("\n");
            sb.Append($"            RefAsync<int> count = 0;");
            sb.Append("\n");
            sb.Append("             return Ok(new{");
            sb.Append("\n");
            sb.Append($"               rows = await _sqlHelper.DB.Queryable<Models.{tableName}>().ToPageListAsync(index, size, count),");
            sb.Append("\n");
            sb.Append("                total = count.Value");
            sb.Append("\n");
            sb.Append("             });");
            sb.Append("\n");
            sb.Append("         }");
            sb.Append("\n");
            sb.Append("         [HttpPost]");
            sb.Append("\n");
            sb.Append($"         public async Task<IActionResult> Add([FromForm] Models.{tableName} {tableName.ToLower()})");
            sb.Append("\n");
            sb.Append("         {");
            sb.Append("\n");
            sb.Append($"             Models.{tableName} add = await _sqlHelper.DB.Insertable({tableName.ToLower()}).RemoveDataCache().ExecuteReturnEntityAsync();");
            sb.Append("\n");
            sb.Append("              return Ok(add);");
            sb.Append("\n");
            sb.Append("         }");
            sb.Append("\n");
            sb.Append("         [HttpPut]");
            sb.Append("\n");
            sb.Append($"         public async Task<IActionResult> Cag([FromForm] Models.{tableName} {tableName.ToLower()})");
            sb.Append("\n");
            sb.Append("         {");
            sb.Append("\n");
            sb.Append($"             int result = await _sqlHelper.DB.Updateable({tableName.ToLower()}).RemoveDataCache().ExecuteCommandAsync();");
            sb.Append("\n");
            sb.Append("              return YesOrNo(result>0);");
            sb.Append("\n");
            sb.Append("         }");
            sb.Append("\n");
            sb.Append("         [HttpDelete]");
            sb.Append("\n");
            sb.Append($"         public async Task<IActionResult> Cag([FromForm] int id)");
            sb.Append("\n");
            sb.Append("         {");
            sb.Append("\n");
            sb.Append($"             int result = await _sqlHelper.DB.Deleteable<Models.{tableName}>().Where(x => x.ID == id).ExecuteCommandAsync();");
            sb.Append("\n");
            sb.Append("              return YesOrNo(result>0);");
            sb.Append("\n");
            sb.Append("         }");
            sb.Append("\n");
            sb.Append("     }");
            sb.Append("\n");
            sb.Append("}");

            using StreamWriter sw = new StreamWriter(fs);

            sw.WriteLine(sb.ToString());
        }

为了方便理解,刻意美化了一下。

OK,代码模板搞好了,该从哪里拿到所有的Model呢?思路是先加载程序集,然后找到存放Model的命名空间,然后找到命名空间下面所有符合条件的Class,然后就可以拿到具体的名称,从而调用代码模板进行文件生成,像这样:

       var assembly = Assembly.Load("程序集名称");

            var types = assembly.ExportedTypes.Where(a => a.FullName.Contains("Model所处的命名空间")).ToList();

       //指定
            string path = $"{Directory.GetCurrentDirectory()}/autoCode";

            foreach (var item in types)
            {
                string tableName = item.FullName.Split('.')[^1];

                Make(tableName, path);
            }

接下来直接运行,走完以后的结果是这样的:

 随便打开一个文件,是这样的:

 效果还是不错的。

如果需要更加精细的控制,可以预先在Model设置特性,然后通过判断特性是否存在来决定如何生成代码,举个栗子:

       var assembly = Assembly.Load("程序集名称");

            var types = assembly.ExportedTypes.Where(a => a.FullName.Contains("Model所处的命名空间")).ToList();

       //指定
            string path = $"{Directory.GetCurrentDirectory()}/autoCode";

            foreach (var item in types)
            {
          //获取所有公开属性
                foreach (var prop in item.GetProperties())
          {
                   MyAttribute attr = method.GetCustomAttribute(typeof(MyAttribute), true) as MyAttribute;
            if(attr is null)
            {
              //进入这里代表该属性没有附加 MyAttribute
            }
                }
            }

当然,还可以获取MyAttribute的属性拿过来进行判断等等。而实际上很多ORM框架也是用类似手段实现Code First、DB First,不过复杂程度比较高。

这样批量生成代码有点像活字印刷,虽然可以解决大量机械重复的工作,但灵活度还是不够高,人脑还是无法替代的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/592067.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【赏】java:编写一个SortedList接口

下面是SortedList接口的示例代码:import java.util.List;public interface SortedList<T extends Comparable<T>> extends List<T> {List<T> sort(List<T> list);int binarySearch(T value); }下面是对于SortedList接口的一个实现示例:import …

如何系统地学习IT技术

从基础技术到高级应用&#xff0c;IT技术发展迅速&#xff0c;我们需要建立系统性的学习方法&#xff0c;才能跟上它的速度。接下来&#xff0c;我将分享我的个人经验&#xff0c;介绍如何系统地学习IT技术&#xff0c;以及如何在快速学习过程中确保自己的技术水平越来越高。 …

加湿助眠仪语音IC芯片 白噪音语音方案 WTN6040F-8S

近年来&#xff0c;随着人们健康意识的不断增强&#xff0c;助眠仪逐渐成为了一种备受欢迎的家居健康设备。随着科技的不断升级&#xff0c;助眠仪也在不断地进行改进&#xff0c;以满足用户需求。其中&#xff0c;一种值得注意的改进就是助眠仪音乐播报芯片的应用。加湿助眠仪…

c++ 11标准模板(STL) std::map(九)

定义于头文件<map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class map;(1)namespace pmr { template <class Key, class T, clas…

国产系统:麒麟之人大金仓数据库部署

一、基本信息和资源 1.1 查看服务器信息 [root7PGxjKPL4 ~]# cat /etc/*release Kylin Linux Advanced Server release V10 (Sword) DISTRIB_IDKylin DISTRIB_RELEASEV10 DISTRIB_CODENAMEjuniper DISTRIB_DESCRIPTION"Kylin V10" DISTRIB_KYLIN_RELEASEV10 DISTRI…

Springboot异步执行

异步执行 1.基于Async注解的方式在异步的方法上加 Async注解&#xff0c;调用接口后基于Async注解的方式优缺点: 2.使用 CompletableFuture 实现异步任务在实现类中创建CompletableFuture 类型的方法优缺点: 3.使用 TaskExecutor 实现异步任务优缺点: 1.基于Async注解的方式 As…

电子企业使用MES管理系统有没有弊端

随着制造业的不断现代化和数字化&#xff0c;越来越多的电子企业开始使用MES生产管理系统。电子企业MES系统是一种用于监控和管理制造业生产过程的软件&#xff0c;能够帮助企业提高生产效率、降低成本、提高质量和灵活性。然而&#xff0c;电子企业使用MES管理系统也存在一些弊…

Autohotkey按键映射

文章目录 功能前缀鼠标按键键盘按键虚拟键码和扫描码实操 功能前缀 尽管在初步使用中已经对常见热键做了说明&#xff0c;但为了本文的完整性&#xff0c;这里还是重新表述一下 #!^<^>!winAltCtrlShiftAlt Gr 其中&#xff0c;<, >为修饰符&#xff0c;用于区分…

使用不同类型注释的小肠路径跟踪深度强化学习

文章目录 Deep Reinforcement Learning for Small Bowel Path Tracking Using Different Types of Annotations摘要本文方法环境stateActionreward 实验结果 Deep Reinforcement Learning for Small Bowel Path Tracking Using Different Types of Annotations 摘要 小肠路径…

令人惊艳的六大算法(哈希表、分治算法、动态规划算法、贪心算法、回溯算法、图论算法)

当谈到计算机科学时&#xff0c;算法是一个重要的话题&#xff0c;因为它们能帮助解决很多问题。有些算法尤其令人惊艳&#xff0c;因为它们不仅高效&#xff0c;而且有着惊人的表现。在这篇文章中&#xff0c;我将分享一些我认为令人惊艳的高效算法。 一、哈希表 哈希表是一种…

通用寄存器-汇编复习(1)

弄清寄存器表达,原理和配件及汇编实验验证。 往期文章: 汇编语言基础-汇编复习(0)_luozhonghua2000的博客-CSDN博客 一个典型的 CPU(此处讨论的不是某一具体的 CPU)由运算器、控制器、寄存器(CPU工作原理)等器件构成,这些器件靠内部总线相连。前一章所说的总线,相对于 CP…

4、USB协议学习:USB的数据包结构

文章目录 数据包结构包(Packet)PID令牌包SETUP&OUT&IN令牌包SOF令牌包 数据包握手包ACK 握手包NAK 握手包 事务(Transaction)Setup事务OUT事务IN事务 传输(Transfer)控制传输中断传输批量传输同步传输/等时传输 端点 数据包结构 USB的通讯数据由多个传输组成&#xff0…

Docker 构建多架构 ARM、x86 AMD image镜像

在当今的计算环境中&#xff0c;各种异构计算设备和平台层出不穷&#xff0c;如何保证应用程序能够在不同的平台和设备上顺利运行&#xff0c;已成为亟待解决的问题。 以一款应用程序为例&#xff0c;它可能需要在 ARM、x86 或 s390x 等不同架构的设备上运行。由于这些设备所使…

Linux—实操篇:关机,重启和用户登录注销

1、关机和重启命令 1.1、基本介绍 shutdown -h now 立即关机 shutdown -h 1 一分钟后关机 shutdown -r now 立即重启 halt 立即关机&#xff0c;作用和上面一样 reboot 立即重启 sync 把内存数据同步到磁盘 注意&#xff1a;仅输入shutdown 默认执行&#xff08;shutdow…

Go开发学习 | 如何快速读取json/yaml/ini等格式的配置文件使用示例

欢迎关注「全栈工程师修炼指南」公众号 点击 &#x1f447; 下方卡片 即可关注我哟! 设为「星标⭐」每天带你 基础入门 到 进阶实践 再到 放弃学习&#xff01; “ 花开堪折直须折&#xff0c;莫待无花空折枝。 ” 作者主页&#xff1a;[ https://www.weiyigeek.top ] 博客&…

docker 数据持久化

目录 一、将本地目录直接映射到容器里&#xff08;运行成容器时候进行映射&#xff09; 二、数据卷模式 1、创建数据卷 2、查看数据卷列表&#xff0c;有哪些数据卷 3、查看某个数据卷 4、容器目录挂载到数据卷 5、数据卷的优势&#xff1a;多个容器共享一个数据卷 默认…

元宇宙应用领域-教育

教育是一个国家发展的基础&#xff0c;在科技发展的时代&#xff0c;元宇宙将会帮助教育行业实现跨越式发展。 元宇宙与教育的结合将会对传统的教学模式带来翻天覆地的变化。它能将线上教学、线下体验、远程互动等优势集于一身&#xff0c;也能把教师从繁重的重复劳动中解放出…

贝叶斯伪标签:鲁棒高效半监督分割的期望最大化

文章目录 Bayesian Pseudo Labels: Expectation Maximization for Robust and Efficient Semi-supervised Segmentation摘要作为期望最大化的伪标签基于变分推理的伪标签的推广实验结果 Bayesian Pseudo Labels: Expectation Maximization for Robust and Efficient Semi-super…

Qt上位机开发-学习记录(一)

一、Qt的安装 下载Qt : https://download.qt.io/ 进入archive/qt/&#xff0c;目前5.14版本下&#xff0c;有直接exe安装的版本&#xff0c;就直接下载 qt-opensource-windows-x86-5.14.2.exe安装Qt : 默认安装&#xff0c;过程中可以先全选 二、新建项目 选择Appliation-&g…

静态代码块、动态代码块、构造方法

类与对象 类&#xff1a;描述事物属性和行为 属性&#xff1a;私有化 行为&#xff1a;公开化 对象&#xff1a;就是类的一个具体实例 代码块&#xff1a; 静态代码块 发生在创建对象之前--时机 随着类的加载而加载 构造代码块 发生在创建对象之前&a…