C#創(chuàng)建一個可快速重復使用的項目模板(詳細過程)
寫在前面
其實很多公司或者資深的開發(fā)都有自己快速創(chuàng)建項目的腳手架的,有的是魔改代碼生成器實現(xiàn),有的直接基于T4,RazorEngine等模板引擎打造;但無論如何,其最終目的其實就是搭建一個自定義項目模板(腳手架)。
今天我們聊聊:如何基于官方的cli donet new
命令創(chuàng)建自己的項目模板。
什么是項目模板
我想用一個命令來說明:
dotnet new list
到這里大家就非常熟悉了,原來大家平時創(chuàng)建項目都是基于已有的模板創(chuàng)建的(紅圈部分大家應該不陌生);我們今天目的就是創(chuàng)建一個這樣的模板,并在vs新建項目時可供選擇創(chuàng)建項目,或者使用cli命令直接創(chuàng)建;
當然,還有公開模板:
https://dotnetnew.azurewebsites.net/
創(chuàng)建自己的模板
1、先準備好一個項目
這里準備的項目就是平時普通的項目,后面會以這個項目為藍本創(chuàng)建模板;因為我最近使用Azure Function類型項目比較多,我就以Function項目為例,其他類型項目同理的;
項目結構圖:
項目文件結構:
D:. │ appsettings.CI.json │ appsettings.Development.json │ appsettings.json │ appsettings.Production.json │ Dockerfile │ Function1.cs │ host.json │ local.settings.json │ MyCompany.Cutapi.FunctionTemp.csproj #這個名字后面要被替換的 │ settings.CI.yaml │ settings.Production.yaml │ Startup.cs │ ├─build │ CD.yaml │ CI.yaml │ _deploy.yaml │ └─deploy │ kustomization.yaml │ ├─base │ deploy.yaml │ kustomization.yaml │ ├─ci │ deploy.yaml │ kustomization.yaml │ └─prod deploy.yaml kustomization.yaml
可以看到其實有很多跟構建,部署等有關的配置文件;
Function1.cs
#模板項目的命名空間 namespace MyCompany.Cutapi.FunctionTemp { public class Function1 { private readonly Stopwatch _sw; private readonly IExtractSegmentService _extractSegmentService; private readonly ILogger<Function1> _logger; public Function1(IExtractSegmentService extractSegmentService, ILogger<Function1> logger) { _sw = new Stopwatch(); _extractSegmentService = extractSegmentService; _logger = logger; } #模板項目的FunctionName 和一些跟隊列有關的配置,這些后面都要 [FunctionName("function1")] [return: ServiceBus("cutapi-queue1-notify", Connection = "ServiceBusConnection")] public async Task<VideoTranscodeNotify> Run([ServiceBusTrigger("cutapi-queue1", Connection = "ServiceBusConnection")] ServiceBusReceivedMessage message , string messageId , ServiceBusMessageActions messageActions , Int32 deliveryCount , DateTime enqueuedTimeUtc , ILogger log ) { _sw.Start(); var messageBody = Encoding.UTF8.GetString(message.Body); log.LogInformation($"{Environment.MachineName} -> function1 begin ->{messageId}: {messageBody}"); await messageActions.CompleteMessageAsync(message); var result = new VideoTranscodeNotify(); try { //todo... } catch (Exception ex) { log.LogError(ex, $"{Environment.MachineName} -> {messageId}:function1 Exception:{ex.Message}"); } _sw.Stop(); log.LogInformation($"{Environment.MachineName} function1 Over ->{messageId} Elapsed: {_sw.Elapsed}"); return result; } } }
以這個文件為例,模板項目里很多文件內(nèi)容都可以按自定義參數(shù)被替換;當然文件名也可以替換;
2、創(chuàng)建配置文件
在項目根目錄下創(chuàng)建配置文件:/.template.config/template.json
結構如下:
├─.template.config
│ template.json
內(nèi)容:
{ "author": "Heiner Wang", //作者 "classifications": [ "Azure Functions" ], //項目歸類 classifications 還會出現(xiàn)在“Tags”列中 "name": "Heiner Function", //項目全名,用戶應看到的模板名稱。 "identity": "HeinerFunction", //項目唯一id "shortName": "hfunc", //項目簡寫 "tags": { "language": "C#", "type": "project" }, "sourceName": "MyCompany.Cutapi.FunctionTemp", //運行模板時使用 -n 或 --name 選項提供要替換的值,不寫了話項目名稱不變 "preferNameDirectory": true, //創(chuàng)建項目的目錄層級; "symbols": { //自定義語法 //自定義參數(shù),新項目命名空間 "Namespace": { "type": "parameter", "dataType": "text", //文本類型 "defaultValue": "Heiner.Function", "replaces": "MyCompany.Cutapi.FunctionTemp" //項目里這個值將會被替換掉 //"fileRename": "MyCompany.Cutapi.FunctionTemp" //也可以指定替換文件名 }, "FunctionName": { "type": "parameter", "dataType": "text", "defaultValue": "function1", "replaces": "function1" }, "QueueName": { "type": "parameter", "dataType": "text", "defaultValue": "cutapi-queue1", "replaces": "cutapi-queue1" }, "EnableRedis": { "type": "parameter", "dataType": "bool", #布爾類型的 "defaultValue": "true" } } }
更多參數(shù)請參考:https://github.com/dotnet/templating/wiki/Reference-for-template.json
代碼段過濾
cs文件
//EnableRedis是自定義參數(shù) #if (EnableRedis) ConnectionMultiplexer redisConnection = ConnectionMultiplexer.Connect(AppSettings.GetConnectionString("Redis")); builder.Services.AddSingleton<IConnectionMultiplexer>(redisConnection); builder.Services.AddSingleton<IDatabase>(c => redisConnection.GetDatabase()); #endif
項目文件
<ItemGroup> <PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" /> <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.9.0" /> <PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.9.0" /> <PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.5" /> </ItemGroup> <ItemGroup Condition="'$(EnableRedis)' == 'True' "> <PackageReference Include="StackExchange.Redis" Version="2.6.48" /> </ItemGroup>
模板文件加入如下配置
??????? "symbols":{...}, "sources": [ { "modifiers": [ { "condition": "(!EnableRedis)", //EnableRedis!=true "exclude": [ //排除下面的文件(這里僅做示例),后面的模板項目當設置參數(shù):EnableRedis==false時,下面的文件就被過濾掉了 "src/MyCompany.Cutapi.FunctionTemp/Redis.cs", ] } ] } ]
???????3、執(zhí)行模板安裝
這一步是將根據(jù)配置文件,將普通項目安裝成一個項目模板,理論上創(chuàng)建自定義模板到這步就完成了;
項目根目錄執(zhí)行:
dotnet new install . 這里命令后面的`.` 是安裝當前目錄的項目的意思; dotnet new install D:\MyCompany.Cutapi.FunctionTemp 也可以這樣,用絕對路徑
更新模板
強制覆蓋安裝
dotnet new install . --force
先刪除再安裝
#先刪除 dotnet new uninstall . #重新安裝 dotnet new install .
后面的.
都代表在項目根目錄執(zhí)行,后面不再贅述;
4、檢查安裝結果
dotnet new list
無論用cli還是vs 都可以看到我們項目模板了,創(chuàng)建模板成功;
參考
5、推送到nuget服務端(可選)
這步是可選的! 注意!很多內(nèi)部模板要脫密處理后再執(zhí)行推送,請勿將機密信息推送到公網(wǎng);
1、模板項目根目錄創(chuàng)建文件MyCompany.Cutapi.FunctionTemp.nuspec
<?xml version="1.0"?> <package > <metadata> <id>HeinerFunction</id> <version>1.0.0</version> <authors>Heiner Wang</authors> <owners>Heiner Wang</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>xxx 公司 Azure Function 快速模板.</description> <tags>dotnet-new;template</tags> </metadata> <files> <file src="**\*" target="content"/> </files> </package>
???????2、生成nuget包
在項目根目錄執(zhí)行
nuget pack MyCompany.Cutapi.FunctionTemp.nuspec
生成nuget包:
HeinerFunction.1.0.0.nupkg
3、推送到服務端
nuget push HeinerFunction.1.0.0.nupkg -Source https://api.nuget.org/v3/index.json -ApiKey YOUR_API_KEY
這步的--Source參數(shù),如果你有搭建好自己的nuget服務端的話改成你自己的;
如何使用一個模板
模板有了,怎么用這個就簡單了;
vs使用
在創(chuàng)建項目時直接選擇自定義模板
不過這樣的話,自定義參數(shù)都是用默認值,所以我還是更推薦用命令行方式;
命令行使用(推薦)
大家做demo的時候都應該執(zhí)行過這樣的命令,其實這就是使用了官方shotname為console
的模板
dotnet new console -n MyConsoleApp1
一樣,自定義模板命令為:
#默認參數(shù) dotnet new hfunc -n MyCompany.Heiner.Test #指定參數(shù) dotnet new hfunc -n MyCompany.Heiner.Test --Namespace MyCompany.Heiner.Test --FunctionName function-live-record --QueueName cutapi-live-record --EnableRedis false
創(chuàng)建成功
[參考]
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
到此這篇關于C#如何創(chuàng)建一個可快速重復使用的項目模板的文章就介紹到這了,更多相關C#如何創(chuàng)建一個可快速重復使用的項目模板內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C# 7.0之ref locals and returns(局部變量和引用返回)
這篇文章主要介紹了C# 7.0之ref locals and returns,即局部變量和引用返回,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03C#如何動態(tài)創(chuàng)建Label,及動態(tài)label事件
這篇文章主要介紹了C#如何動態(tài)創(chuàng)建Label,及動態(tài)label事件,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04