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

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

思路分析

众所周知,利用反射可以在程序运行时获取到任一对象的类型、属性、参数、方法等,并加以调用,利用这些获取到的可以在程序运行时追加各种自定义的功能。以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://xiahunao.cn/news/256479.html

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

相关文章

JAVA企业级开发 1.5 初探Spring AOP

一、提出游吟诗人唱赞歌任务 骑士执行任务前和执行任务后&#xff0c;游吟诗人唱赞歌 &#xff08;一&#xff09;采用传统方式实现 修改day04子包的勇敢骑士类 修改day04子包里的救美骑士类 执行测试类 - TestKnight &#xff08;二&#xff09;采用传统方式实现的缺…

【JavaSE】Java基础语法(三十九):网络编程入门

文章目录 1. 网络编程概述2. 网络编程三要素3. IP地址4. InetAddress5. 端口和协议 1. 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络 操作系统&#xff0c;网络管理软件及网络通信协…

欧拉与莫比乌斯

更多文章可以在本人的个人小站&#xff1a;https://kaiserwilheim.github.io 查看。 转载请注明出处。 初稿写于2021-10-10&#xff0c; 再修改于2022-02-07 Achtung: 本文章使用p来代指“任意质数”&#xff0c;请勿混淆。 首先让我们膜拜一下莱昂哈德欧拉(Leonhard Euler)…

贝塞尔

贝塞尔曲线可视化链接 介绍&#xff1a; 贝塞尔曲线&#xff0c;又称贝兹曲线或贝济埃曲线&#xff0c;是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线&#xff0c;贝兹曲线由线段与节点组成&#xff0c;节点是可拖动的支点&#xff0c;线段像可…

详解人工智能的五大思想流派 元芳你支持哪一派?

▼ 点击上方蓝字 关注网易智能 聚焦AI&#xff0c;读懂下一个大时代&#xff01; 【网易智能讯 3月1日消息】未来的就业形势还能依靠科技巨头和首席执行官们来决定&#xff0c;而人工智能的未来&#xff0c;依旧充满了太多的不确定性。 这一状况是源自于人工智能及其在科技行业…

【科大讯飞】全球首款,Mobius莫比斯同声翻译耳机 ,AI智能运动耳机 ,支持英日法韩俄西班牙6种语音...

© 程序员严选 丨 为您甄选全球好物 科大讯飞重磅推出 翻译界的最新黑科技神器 同声翻译 智能耳机 对方说外语&#xff0c;耳机就会同声语音翻译出来哦~ 。。。 著名语音AI品牌科大讯飞与咪咕联合打造了一款智能翻译耳机&#xff0c;全球首款全语音人工智能耳机——Mobius…

DailyMart03:如何基于DDD设计商城的领域模型?

大家好&#xff0c;我是飘渺。既然有人催更那今天咱们就继续更新DDD&微服务系列&#xff01; 在面向对象开发中&#xff0c;所有事物都可以看作是对象。然而&#xff0c;在日常开发中&#xff0c;我们通常从数据出发来设计对象的表现形式&#xff0c;这种做法侧重于数据属性…

哈萨比斯的人类补完计划

在著名动漫《新世纪福音战士》里&#xff0c;碇源堂和他背后的SEELE组织始终在执行一项叫做“人类补完计划”的神秘行动。 这个计划到底是什么意思&#xff0c;粉丝们已经争吵了很多年。但大体上应该是说利用“神性”来补完人类族群&#xff0c;从而消除人类社会中的种种问题。…

阿基里斯之踵

阿基里斯是古希腊神话中最伟大的英雄之一。相传&#xff0c;他的母亲是一位女神&#xff0c;在他降生之初&#xff0c;女神为了使他长生不死&#xff0c;将他浸入冥河洗礼。阿基里斯从此刀枪不入&#xff0c;百毒不侵&#xff0c;只有一点除外———他的脚踵当时被女神提在手中…

麦比乌斯带

数学家们吐露&#xff0c;麦比乌斯带只有单面&#xff0c;如果你要将它分成两半&#xff0c;你将会感到十分可笑&#xff0c;因为分开后还是一条带。 莫比乌斯环的奇妙之处有三&#xff1a; 一、莫比乌斯环只存在一个面。 二、如果沿着莫比乌斯环的中间剪开&#xff0c;将会形成…

数字与能源,交织成新基建的摩比斯环

提到新基建&#xff0c;大家可能会首先想起大数据、AI、云计算组成的数字产业&#xff0c;以及高铁、城轨、新能源汽车构成的交通产业。但如果你留心分析&#xff0c;会发现新基建的体系里还有一条“暗线”——那就是能源。 无论直接指向能源升级的特高压、充电桩&#xff0c;还…

塞尔希奥·阿奎罗和 The Sandbox 携手合作,激活元宇宙足球迷!

五次英超联赛冠军兼创纪录的得分球员选择了 The Sandbox 平台来创建他的第一个虚拟世界。 简要介绍 阿根廷在串流媒体和游戏领域上的足球传奇人物和全球典范将继续建立新的数字社区&#xff0c;这一次是与 The Sandbox 中的独特空间 Kuniverse。 来自世界各地的球迷将能够关注阿…

莫比乌斯详细介绍

莫比乌斯反演 莫比乌斯反演是数论数学中很重要的内容&#xff0c;可以用于解决很多组合数学的问题。 莫比乌斯函数 莫比乌斯函数&#xff0c;数论函数&#xff0c;由德国数学家和天文学家莫比乌斯提出。梅滕斯首先使用μ(n)作为莫比乌斯函数的记号。 莫比乌斯函数是指以下的…

无主之地kill ajax,阿克斯顿 - 无主之地中文维基 - 灰机wiki

阿克斯顿 艾克斯顿和军刀枪塔 角色类型可选角色(无主之地2) NPC(无主之地&#xff1a;前奏) 性别男性 种族人类 Axton is the playable Commando class character in Borderlands 2 Launch Date Trailer. 背景 Originally from Hieronymous, Axton spent ten years with the Da…

Mahalanobis(马哈拉诺比斯)距离

马氏距离(Mahalanobis Distance)是一种距离的度量&#xff0c;可以看作是欧氏距离的一种修正&#xff0c;修正了欧式距离中各个维度尺度不一致且相关的问题。 马氏距离&#xff08;Mahalanobis Distance&#xff09;是由马哈拉诺比斯&#xff08;P. C. Mahalanobis&#xff09;…

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

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

想把手机内容投屏到电脑 并且可以用电脑控制手机怎么办,很简单

首先打开设置&#xff0c;点击应用》可选功能 点击 查看功能 搜索 无线显示器点击下一步 点击安装 等待安装完成 完成后我们打开 系统》投影到此电脑 把设置改为以下选项&#xff0c;然后单击启动两家应用以投影到此电脑 出现这个画面就对了&#xff0c;接下来我们开始调试手…

发现了一个很好用的电脑上用电脑控制安卓手机的软件

2019独角兽企业重金招聘Python工程师标准>>> 发现了一个很好用的电脑上用电脑控制安卓手机的软件scrcpy&#xff0c; 还是开源的 地址&#xff1a; https://github.com/Genymobile/scrcpy windows,mac os,linux都支持。 基本上没有延迟&#xff0c;电脑屏幕显示安卓…

图解:手机控制电脑的软件的使用教程

在使用IP软件时总是掉线&#xff0c;有时又要出去&#xff0c;不能总呆在电脑旁&#xff0c;所以使用了一个手机控制电脑的软件 使用方法&#xff1a;电脑下载一个这个软件&#xff0c;手机下载一个 下载地址官网&#xff1b;https://www.teamviewer.com/en/download/windows…