校园类网站模板免费下载,广告建设网站建设,百度恶意屏蔽网站,网站视频下载软件图片gif无法查看#xff0c;请查看原文至博客园查看详情。目录目录ABPHelper.CLIScriban通过Microsoft.Extensions.FileProviders.Embedded获取嵌入资源通过静态方法获取文件内容使用Microsoft.Extensions.FileProviders.Physical获取文件内容Microsoft.CodeAnalysis.CSharpHu… 图片gif无法查看请查看原文至博客园查看详情。目录目录ABPHelper.CLIScriban通过Microsoft.Extensions.FileProviders.Embedded获取嵌入资源通过静态方法获取文件内容使用Microsoft.Extensions.FileProviders.Physical获取文件内容Microsoft.CodeAnalysis.CSharpHumanizer.CoreSystem.CommandLineElsa入门使用指南命令行技术点如下AbpHelper.GUIABPHelper.CLIAbpHelper is a tool that helps you with developing Abp vNext applications.https://github.com/EasyAbp/AbpHelper.CLI命令行CLI实现ABP VNEXT中CRUD代码的生成用户只需要创建一个实体类即可生成该表的CRUD并添加到项目中。使用前请确保备份您的源文件入门安装 AbpHelper CLI 工具dotnet tool install EasyAbp.AbpHelper -g如果您更喜欢GUI那么还有一个UI工具: AbpHelper.GUI如果以前安装过请使用以下命令更新它:dotnet tool update EasyAbp.AbpHelper -g使用 ABP CLI 创建一个ABP 应用abp new MyToDo创建实体public class Todo : FullAuditedEntityGuid
{public string Content { get; set; }public bool Done { get; set; }
}运行 AbpHelperabphelper generate crud Todo -d C:\MyTodogenerate crud 是生成CRUD文件的子命令Todo 指定了我们先前创建的实体名-d 指定了由ABP CLI创建的ABP项目的根目录AbpHelper 将生成所有的CRUD , 甚至包括添加迁移和数据库更新运行这个 DbMigrator 项目去迁移数据库启动你的应用用默认的管理员帐户登录看到神奇的事发生了如果看不到 TODO 菜单,请检查您的权限并确保授予了TODO相关的权限使用指南运行abphelper -h 查看帮助类似地您可以使用 -h或--help 选项查看以下每个命令的详细用法命令行generate为ABP项目生成文件. 使用 abphelper generate --help 获取详情crud根据指定实体生成一组与CRUD相关的文件abphelper generate crud Todoservice根据指定的名称生成服务接口和类文件abphelper generate service Project -f ProjectmethodsGenerate service method(s) according to the specified name(s)根据指定名称给service 增加方法abphelper generate methods Login Logout -s ProjectlocalizationGenerate localization item(s) according to the specified name(s)根据指定名称生成localization 本地化项abphelper generate localization MyItem1 MyItem2 MyItem3controllerabphelper generate controller Todo
Generate controller class and methods according to the specified service 技术点如下ScribanMicrosoft.Extensions.FileProviders.EmbeddedMicrosoft.CodeAnalysis.CSharpSystem.CommandLineElsaHumanizer.Core如果我们想实现代码生成器我们需要解决什么问题呢。提供.NET接口的模板引擎比如Razor,Sciban等模板一般放在文件中我们需要知道如何读取这些资源文件文本文件。如果我们使用code first通常需要创建一个实体类当创建好一个类后怎么解析出这个类名属性命名空间呢而不是另外去输入这些参数。(只需要代码的路径)实体名Name比如BaseItem命名空间NameSpace LinCms.Base.BaseItems或Volo.Abp.BaseItems主键类型PrimaryKey比如是Guid,还是int还是long明确有哪些变量如何控制输入。模板的位置TemplatePath ./Templates根据模板生成的代码的输出目录OutputDirectory 相对路径 或 绝对路径 ./output 或 D:/code/github/code-scaffoldingScribanScriban是一种快速、强大、安全和轻量级的文本模板语言和.NET引擎具有解析liquid模板的兼容模式【翻译】Scriban是一种快速、强大、安全和轻量级的文本模板语言和.NET引擎具有解析liquid模板的兼容模式【翻译】 Scriban language 待完成【翻译】Scriban runtime 待完成创建一个xunit测试项目引入包ScibanPackageReference IncludeScriban Version3.0.0-alpha.3 /
做一个小测试[Fact]
public void Test1()
{var template Template.Parse(Hello {{name}}!);var result template.Render(new { Name World });Assert.Equal(Hello World!, result);
}
ctrlr ctrlt 运行测试正常。写一个我们仓储接口。 [Fact]public void Test9(){var template Template.Parse(using LinCms.Core.Entities;
namespace LinCms.Core.IRepositories
{public interface I{{ entity_name }}Repository : IAuditBaseRepository{{ entity_name }}{}
});var result template.Render(new { EntityName Doc });Assert.Equal(using LinCms.Core.Entities;
namespace LinCms.Core.IRepositories{public interface IDocRepository : IAuditBaseRepositoryDoc{}}.Replace(\r\n, ).Replace( , ), result.Replace(\r\n, ).Replace( , ));}最终生成的效果是using LinCms.Core.Entities;
namespace LinCms.Core.IRepositories
{public interface IDocRepository : IAuditBaseRepositoryDoc{}
}
通过Microsoft.Extensions.FileProviders.Embedded获取嵌入资源这是一个嵌入资源Provider提供嵌入资源的获取比如我们写的Sciban的模板文件。xunit测试项目引入包PackageReference IncludeMicrosoft.Extensions.FileProviders.Embedded Version3.1.6 /
创建一个测试类FileTest
[Fact]
public void FileProviderTest()
{IFileProvider fileProvider new ManifestEmbeddedFileProvider(Assembly.GetAssembly(typeof(FileTest)));
}
出现这个错 System.InvalidOperationException:“Could not load the embedded file manifest Microsoft.Extensions.FileProviders.Embedded.Manifest.xml for assembly OvOv.Test.”打开OvOv.Test.csproject PropertyGroup增加如下一行GenerateEmbeddedFilesManifesttrue/GenerateEmbeddedFilesManifest新建目录Templates新建文本文件 IRepository.txt右键属性生成操作嵌入的资源可不选复制到输出目录using LinCms.Core.Entities;
namespace LinCms.Core.IRepositories
{public interface I{{ entity_ame }}Repository : IAuditBaseRepository{{ entity_ame }}{}
}
可修改csproject文件设置Templates目录下都是嵌入式资源ItemGroupEmbeddedResource IncludeTemplates\**\** /
/ItemGroup
在测试方法中通过GetFileInfo得到IFileInfo.通过stream进行读取文本并输出。private readonly ITestOutputHelper output;
public FileTest(ITestOutputHelper output)
{this.output output;
}[Fact]
public void GetTextTest()
{IFileProvider fileProvider new ManifestEmbeddedFileProvider(Assembly.GetAssembly(typeof(FileTest)));IFileInfo fileInfo fileProvider.GetFileInfo(./Templates/IRepository.txt);string text;using (var stream fileInfo.CreateReadStream()){using (var streamReader new StreamReader(stream, Encoding.UTF8, true)){text streamReader.ReadToEnd();}}output.WriteLine(text);
}
通过静态方法获取文件内容不用嵌入式资源需要右键文件 属性复制到输出目录如果较新则复制可不选生成操作[Fact]
public void ReadAllText()
{string text File.ReadAllText(./Templates/IRepository.txt);output.WriteLine(text);
}
使用Microsoft.Extensions.FileProviders.Physical获取文件内容引用包PackageReference IncludeMicrosoft.Extensions.FileProviders.Physical Version3.1.6 /
[Theory]
[InlineData(./Templates/IRepository.txt)]
public void PhysicalFileProviderReadText(string path)
{var current Environment.CurrentDirectory;var fileProvider new PhysicalFileProvider(current);IFileInfo fileInfo fileProvider.GetFileInfo(path);string text;using (var stream fileInfo.CreateReadStream()){using (var streamReader new StreamReader(stream, Encoding.UTF8, true)){text streamReader.ReadToEnd();}}output.WriteLine(text);
}
var current Environment.CurrentDirectory; 这行代码能得到当前的目录因为设置为输出 所以当前目录下有templates文件夹并有IRepository.txtD:\\code\\gitee\\Code\\OvOv.Test\\bin\\Debug\\netcoreapp3.1
Microsoft.CodeAnalysis.CSharp代码生成还需要什么呢创建一个实体类根据此实体类生成表的CRUD代码。修改OvOv.Test,引入包 PackageReference IncludeMicrosoft.CodeAnalysis.CSharp Version3.6.0 /
这个包是https://github.com/dotnet/roslyn的一部分.Roslyn 是.NET编译器为C#和Visual Basic 提供了丰富的代码分析API。再搞个CodeAnalysisTest测试类。这里我们有一个字符串他是一个实体类这个类有一些特点。比如命名空间namespace类名 class继承的父类泛型类型 guid有二个属性author,title如下代码通过语法树解析出这个字符串中的命名空间输出 LinCms.Books。说明: FullAduitEntity是一个包含CRUD的审计实体类通常包含七个字段创建人创建时间修改人修改时间是否删除删除人删除时间另外还有一个主键。默认是long具体可查看此文件https://github.com/luoyunchong/lin-cms-dotnetcore/blob/master/src/LinCms.Core/Entities/FullAduitEntity.cs你也可以使用诸如EntityGuid即一个泛型的实体类即可。public class EntityT
{public T Id { get; set; }
}
[Fact]
public void GetNamespace()
{string text
namespace LinCms.Books
{public class Book : FullAduitEntityGuid{public string Author { get; set; }public string Title { get; set; }}
};SyntaxTree tree CSharpSyntaxTree.ParseText(text);CompilationUnitSyntax root tree.GetCompilationUnitRoot();var namespace root.DescendantNodes().OfTypeNamespaceDeclarationSyntax().Single().Name.ToString();output.WriteLine(namespace);
}
获取类名.className为BookClassDeclarationSyntax classDeclarationSyntax root.DescendantNodes().OfTypeClassDeclarationSyntax().Single();
string className classDeclarationSyntax.Identifier.ToString();
获取父类baseType为FullAduitEntity 主键类型primaryKey值为Guid BaseListSyntax baseList classDeclarationSyntax.BaseList!;
var genericNameSyntax baseList.DescendantNodes().OfTypeSimpleBaseTypeSyntax().First(node !node.ToFullString().StartsWith(I)) // Not interface.DescendantNodes().OfTypeGenericNameSyntax().FirstOrDefault();string baseType;
string? primaryKey;
if (genericNameSyntax null)
{// No generic parameter - Entity with Composite KeysbaseType baseList.DescendantNodes().OfTypeSimpleBaseTypeSyntax().Single().Type.ToString();primaryKey long;
}
else
{// Normal entitybaseType genericNameSyntax.Identifier.ToString();primaryKey genericNameSyntax.DescendantNodes().OfTypeTypeArgumentListSyntax().Single().Arguments[0].ToString();
}
获取该类的属性集合。var properties root.DescendantNodes().OfTypePropertyDeclarationSyntax().Select(prop new PropertyInfo(prop.Type.ToString(), prop.Identifier.ToString())).ToList();
其中PropertyInfo是用来存储属性集合的实体类public class PropertyInfo
{public string Type { get; }public string Name { get; }public PropertyInfo(string type, string name){Type type;Name name;}
}
我们通过debugger查看局部变量。Humanizer.CoreHumanizer可以用来处理strings, enums, dates, times, timespans, numbers and quantities所有的需求。https://github.com/Humanizr/Humanizer当我们写代码时总避免不了写复数形式的代码一些特殊的后缀不是直接加s就行的。所以可以用Humanizer来处理这些特殊的变量转下划线 Underscore复数形式比如取集合数据时变量名 Pluralize转小驼峰写法比如变量 Camelize更多直接看README通过扩展方法生成这些字符串。public class EntityInfo
{public EntityInfo(string name){Name name;}public string Name { get; }/// summary/// 复数/// /summarypublic string NamePluralized Name.Pluralize();/// summary/// 首字母小写/// /summarypublic string NameCamelize Name.Camelize();/// summary/// 小写复数/// /summarypublic string NameCamelizePluralized Name.Camelize().Pluralize();}
System.CommandLinehttps://github.com/dotnet/command-line-apiSystem.CommandLine是一组用于构建命令行应用程序的库包括解析调用和渲染。他能简化命令行参数的处理帮助我们构建自己的CLI。对于代码生成器不要是必须的。Elsahttps://github.com/elsa-workflows/elsa-coreElsa Core是一个工作流库可在任何 .NET Core应用程序中执行工作流。工作流可以不仅使用代码来定义也可作为JSONYAML或XML。代码生成器流程多可使用此程序工作流来处理。不是必须的。AbpHelper.GUIhttps://github.com/EasyAbp/AbpHelper.GUIAbpHelper is a tool that helps you with developing Abp vNext applications. It can be used to call ABP CLI, generate code, manage modules, etc.ABP VNEXT的代码生成的可视化界面使用方式看README就好不多介绍。帮助ABP VNext的开发者快速构建单表的CRUD的。如果你自己研究一下这些类库的使用方法特别是Sciban。我们也能实现代码生成器帮助改善公司及自己已有项目的开发流程。