经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C#如何创建一个可快速重复使用的项目模板
来源:cnblogs  作者:乔达摩(嘿~)  时间:2024/6/25 8:55:11  对本文有异议

写在前面

其实很多公司或者资深的开发都有自己快速创建项目的脚手架的,有的是魔改代码生成器实现,有的直接基于T4,RazorEngine等模板引擎打造;但无论如何,其最终目的其实就是搭建一个自定义项目模板(脚手架)。

今天我们聊聊:如何基于官方的cli donet new 命令创建自己的项目模板。

什么是项目模板

我想用一个命令来说明:

  1. dotnet new list

image-20240515170358858

到这里大家就非常熟悉了,原来大家平时创建项目都是基于已有的模板创建的(红圈部分大家应该不陌生);我们今天目的就是创建一个这样的模板,并在vs新建项目时可供选择创建项目,或者使用cli命令直接创建;

当然,还有公开模板:

https://dotnetnew.azurewebsites.net/

创建自己的模板

1、先准备好一个项目

这里准备的项目就是平时普通的项目,后面会以这个项目为蓝本创建模板;因为我最近使用Azure Function类型项目比较多,我就以Function项目为例,其他类型项目同理的;

项目结构图:

image-20240515171904545

项目文件结构:

  1. D:.
  2. appsettings.CI.json
  3. appsettings.Development.json
  4. appsettings.json
  5. appsettings.Production.json
  6. Dockerfile
  7. Function1.cs
  8. host.json
  9. local.settings.json
  10. MyCompany.Cutapi.FunctionTemp.csproj #这个名字后面要被替换的
  11. settings.CI.yaml
  12. settings.Production.yaml
  13. Startup.cs
  14. ├─build
  15. CD.yaml
  16. CI.yaml
  17. _deploy.yaml
  18. └─deploy
  19. kustomization.yaml
  20. ├─base
  21. deploy.yaml
  22. kustomization.yaml
  23. ├─ci
  24. deploy.yaml
  25. kustomization.yaml
  26. └─prod
  27. deploy.yaml
  28. kustomization.yaml

可以看到其实有很多跟构建,部署等有关的配置文件;

Function1.cs

  1. #模板项目的命名空间
  2. namespace MyCompany.Cutapi.FunctionTemp
  3. {
  4. public class Function1
  5. {
  6. private readonly Stopwatch _sw;
  7. private readonly IExtractSegmentService _extractSegmentService;
  8. private readonly ILogger<Function1> _logger;
  9. public Function1(IExtractSegmentService extractSegmentService, ILogger<Function1> logger)
  10. {
  11. _sw = new Stopwatch();
  12. _extractSegmentService = extractSegmentService;
  13. _logger = logger;
  14. }
  15. #模板项目的FunctionName 和一些跟队列有关的配置,这些后面都要
  16. [FunctionName("function1")]
  17. [return: ServiceBus("cutapi-queue1-notify", Connection = "ServiceBusConnection")]
  18. public async Task<VideoTranscodeNotify> Run([ServiceBusTrigger("cutapi-queue1", Connection = "ServiceBusConnection")] ServiceBusReceivedMessage message
  19. , string messageId
  20. , ServiceBusMessageActions messageActions
  21. , Int32 deliveryCount
  22. , DateTime enqueuedTimeUtc
  23. , ILogger log
  24. )
  25. {
  26. _sw.Start();
  27. var messageBody = Encoding.UTF8.GetString(message.Body);
  28. log.LogInformation($"{Environment.MachineName} -> function1 begin ->{messageId}: {messageBody}");
  29. await messageActions.CompleteMessageAsync(message);
  30. var result = new VideoTranscodeNotify();
  31. try
  32. {
  33. //todo...
  34. }
  35. catch (Exception ex)
  36. {
  37. log.LogError(ex, $"{Environment.MachineName} -> {messageId}:function1 Exception:{ex.Message}");
  38. }
  39. _sw.Stop();
  40. log.LogInformation($"{Environment.MachineName} function1 Over ->{messageId} Elapsed: {_sw.Elapsed}");
  41. return result;
  42. }
  43. }
  44. }

以这个文件为例,模板项目里很多文件内容都可以按自定义参数被替换;当然文件名也可以替换;

2、创建配置文件

在项目根目录下创建配置文件:/.template.config/template.json

结构如下:

├─.template.config
│ template.json

内容:

  1. {
  2. "author": "Heiner Wang", //作者
  3. "classifications": [ "Azure Functions" ], //项目归类 classifications 还会出现在“Tags”列中
  4. "name": "Heiner Function", //项目全名,用户应看到的模板名称。
  5. "identity": "HeinerFunction", //项目唯一id
  6. "shortName": "hfunc", //项目简写
  7. "tags": {
  8. "language": "C#",
  9. "type": "project"
  10. },
  11. "sourceName": "MyCompany.Cutapi.FunctionTemp", //运行模板时使用 -n 或 --name 选项提供要替换的值,不写了话项目名称不变
  12. "preferNameDirectory": true, //创建项目的目录层级;
  13. "symbols": { //自定义语法
  14. //自定义参数,新项目命名空间
  15. "Namespace": {
  16. "type": "parameter",
  17. "dataType": "text", //文本类型
  18. "defaultValue": "Heiner.Function",
  19. "replaces": "MyCompany.Cutapi.FunctionTemp" //项目里这个值将会被替换掉
  20. //"fileRename": "MyCompany.Cutapi.FunctionTemp" //也可以指定替换文件名
  21. },
  22. "FunctionName": {
  23. "type": "parameter",
  24. "dataType": "text",
  25. "defaultValue": "function1",
  26. "replaces": "function1"
  27. },
  28. "QueueName": {
  29. "type": "parameter",
  30. "dataType": "text",
  31. "defaultValue": "cutapi-queue1",
  32. "replaces": "cutapi-queue1"
  33. },
  34. "EnableRedis": {
  35. "type": "parameter",
  36. "dataType": "bool", #布尔类型的
  37. "defaultValue": "true"
  38. }
  39. }
  40. }

更多参数请参考:https://github.com/dotnet/templating/wiki/Reference-for-template.json

代码段过滤

cs文件

  1. //EnableRedis是自定义参数
  2. #if (EnableRedis)
  3. ConnectionMultiplexer redisConnection = ConnectionMultiplexer.Connect(AppSettings.GetConnectionString("Redis"));
  4. builder.Services.AddSingleton<IConnectionMultiplexer>(redisConnection);
  5. builder.Services.AddSingleton<IDatabase>(c => redisConnection.GetDatabase());
  6. #endif

项目文件

  1. <ItemGroup>
  2. <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
  3. <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.0" />
  4. <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.9.0" />
  5. <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
  6. <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" />
  7. </ItemGroup>
  8. <ItemGroup Condition="'$(EnableRedis)' == 'True' ">
  9. <PackageReference Include="StackExchange.Redis" Version="2.6.48" />
  10. </ItemGroup>

文件过滤

模板文件加入如下配置

  1. "symbols":{...},
  2. "sources": [
  3. {
  4. "modifiers": [
  5. {
  6. "condition": "(!EnableRedis)", //EnableRedis!=true
  7. "exclude": [ //排除下面的文件(这里仅做示例),后面的模板项目当设置参数:EnableRedis==false时,下面的文件就被过滤掉了
  8. "src/MyCompany.Cutapi.FunctionTemp/Redis.cs",
  9. ]
  10. }
  11. ]
  12. }
  13. ]

3、执行模板安装

这一步是将根据配置文件,将普通项目安装成一个项目模板,理论上创建自定义模板到这步就完成了;

项目根目录执行:

  1. dotnet new install .
  2. 这里命令后面的`.` 是安装当前目录的项目的意思;
  3. dotnet new install D:\MyCompany.Cutapi.FunctionTemp
  4. 也可以这样,用绝对路径

更新模板

强制覆盖安装

  1. dotnet new install . --force

先删除再安装

  1. #先删除
  2. dotnet new uninstall .
  3. #重新安装
  4. dotnet new install .

后面的.都代表在项目根目录执行,后面不再赘述;

4、检查安装结果

  1. dotnet new list

image-20240515180319820

image-20240515180417880

无论用cli还是vs 都可以看到我们项目模板了,创建模板成功;

参考

5、推送到nuget服务端(可选)

这步是可选的! 注意!很多内部模板要脱密处理后再执行推送,请勿将机密信息推送到公网;

1、模板项目根目录创建文件MyCompany.Cutapi.FunctionTemp.nuspec

  1. <?xml version="1.0"?>
  2. <package >
  3. <metadata>
  4. <id>HeinerFunction</id>
  5. <version>1.0.0</version>
  6. <authors>Heiner Wang</authors>
  7. <owners>Heiner Wang</owners>
  8. <requireLicenseAcceptance>false</requireLicenseAcceptance>
  9. <description>xxx 公司 Azure Function 快速模板.</description>
  10. <tags>dotnet-new;template</tags>
  11. </metadata>
  12. <files>
  13. <file src="**\*" target="content"/>
  14. </files>
  15. </package>

2、生成nuget包

在项目根目录执行

  1. nuget pack MyCompany.Cutapi.FunctionTemp.nuspec

生成nuget包:

HeinerFunction.1.0.0.nupkg

3、推送到服务端

  1. nuget push HeinerFunction.1.0.0.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey YOUR_API_KEY

这步的--Source参数,如果你有搭建好自己的nuget服务端的话改成你自己的;

如何使用一个模板

模板有了,怎么用这个就简单了;

vs使用

在创建项目时直接选择自定义模板

image-20240516093813918

不过这样的话,自定义参数都是用默认值,所以我还是更推荐用命令行方式;

命令行使用(推荐)

大家做demo的时候都应该执行过这样的命令,其实这就是使用了官方shotname为console的模板

  1. dotnet new console -n MyConsoleApp1

一样,自定义模板命令为:

  1. #默认参数
  2. dotnet new hfunc -n MyCompany.Heiner.Test
  3. #指定参数
  4. dotnet new hfunc -n MyCompany.Heiner.Test --Namespace MyCompany.Heiner.Test --FunctionName function-live-record --QueueName cutapi-live-record --EnableRedis false

创建成功

image-20240516155502856

[参考]

https://learn.microsoft.com/zh-cn/dotnet/core/tools/custom-templates

https://cloud.tencent.com/developer/article/2319366

https://github.com/dotnet/templating/wiki/Reference-for-template.json

原文链接:https://www.cnblogs.com/xiaxiaolu/p/18259750

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号