Visual Studio多專案範本紀錄

Visual Studio 2022 多專案範本紀錄, 一直想應用多專案範本但沒有符合成本效益的專案就只能做到毛皮的層度。最近個有系統平台昇級移轉的專案,將有數十個 WebApp 要進行重構昇級多專案範本的效益終於派上用場了。VS2022, How to create a solution template with multiple projects.

專案範本與項目範本

Visual Studio 的範本有專案範本(Project Templates)與項目範本(Item Templates)。

專案範本與項目範本提供可重複使用的虛設常式,讓使用者有一些基本的程式碼和結構可依其目的來自行自訂。安裝 Visual Studio 時會安裝一些預先定義的專案範本和項目範本。

您可以使用已安裝範本、撰寫自己的自訂範本,或下載並使用社群所建立的範本。 如需詳細資訊,請參閱 如何:建立專案範本如何:建立項目範本

(單)專案範本

本篇文章重心在多專案範本。單專案範本的實作很簡單使用匯出範本精靈」功能即可。請參考 如何:建立專案範本

匯出範本精靈」將會匯出MyTemplate.vstemplate專案範本檔,請認真解讀。

多專案範本

多專案範本是大部份系統的普遍狀況。比如典型的三層應用系統框架,一個方案整合三個專案:App Project、Biz Project、DB Project。

多專案範本實作簡述

「多專案範本」的實作其實就是把數個「(單)專案範本」整合在一起,所以要先會實作單專案範本才能學多專案範本實作。

多專案範本用一個根專案範本檔Root.vstemplate把相關聯的(單)專案範本整合在一起。官方提供的文章,如何:建立多專案範本,有看沒有懂不過還是要看一遍。有找到這二篇不錯的參考文章:

專案範本基本參數 $projectname$$safeprojectname$

在 Visual Studio 建立新專案時,一定要輸入專案名稱會以名為$projectname$的參數進行傳遞。基本上也只有這個基本參數可用。基他參實需再實作IWizard 介面這是進階的進階就不實作了。

$projectname$為基礎演算出另一個專案名稱$safeprojectname$,差別在去除了不安全的字元。還有其他範本參數不過並不關鍵。

父代範本的變數:ext_*

當從根專案範本傳遞到子專案範本的變數名稱其前置詞要加上"ext_"如:

  • $projectname$$ext_projectname$

  • $safeprojectname$$ext_projectname$

ext_ 前置詞新增至任何參數,以參考父代範本的變數。 例如: ext_safeprojectname

多專案範本參數 $projectname$ 傳遞

參數的傳遞由根專案範本傳遞到(子)專案範本預設沒有打開所以要自己打開。

<ProjectTemplateLink ProjectName="$projectname$" CopyParameters="true"> 
<!-- 其中屬性 CopyParameters="true" 為必需才會把參數送到子層 -->

套用範本參數時,有些原始碼檔預設沒有打開套用參數故需自己手動打開。

<ProjectItem ReplaceParameters="true" TargetFileName="_Imports.razor">_Imports.razor</ProjectItem>
<!-- 其中屬性 ReplaceParameters="true" 為必需才會套用範本參數。 -->

這樣原始碼中的範本變數才會被套用,如下例:

_Imports.razor
@using System.Net.Http
@using Microsoft.AspNetCore.Components.Web
...
@using $safeprojectname$.Services    //<------ 將套用範本參數 
@using $safeprojectname$.Shared      //<------ 將套用範本參數
SampleBiz.cs
using System;
using System.Collections.Generic;
using System.Linq;
using $safeprojectname$.Services;  //<------ 將套用範本參數

namespace $safeprojectname$.DEMO;  //<------ 將套用範本參數

class SampleBiz
{
    readonly ILogger<SampleBiz> _logger;
    public SampleBiz(ILogger<SampleBiz> logger)
    {
        _logger = logger;
    }
    ...
}
AssemblyInfo.cs
using System.Runtime.CompilerServices;

/// Friend Assembly
[assembly: InternalsVisibleTo("$ext_projectname$")] //<------ 將套用父代範本參數
[assembly: InternalsVisibleTo("Vista.Biz")]

多專案範本檔實作階段過程紀錄

階段一、使用匯出範本精靈」功能匯出同下方案(solution)下的相關聯專案(csproject),本例如下:

階段二、解開各個專案範 zip 的後自己手動加入 Root.vstemplate 根專案範本檔與編輯它。也可以加入icon檔__TemplateIcon.ico包裝一下。這階段的工作是全手工作業。大概如下:

階段三、完成後再手動 zip 打包放入Vsual Studio 範本目錄。其中階段二、三的範本參數傳遞的調整與測試可能要跑好幾個回合才會如計畫。最後結果大概如下:

多專案範本檔(Root.vstemplate)紀錄

基本上多專案範本是全手工作業。先準備好各個專案的範本。再用Root.vstemplate檔案整合它們。

多專案之根範本主檔:Root.vstemplate

Root.vstemplate
<VSTemplate Version="3.0.0" Type="ProjectGroup" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
  <TemplateData>
    <!-- 根專案範本的基本資料。 -->
    <Name>SKBEarthApp</Name>
    <Description>新光新地球應用專案.v13</Description>
    <ProjectType>CSharp</ProjectType>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <!-- 以下是相關聯的(子)專案範本,此例有三個。 -->
    <ProjectCollection>
      <ProjectTemplateLink ProjectName="$projectname$">
        SKBEarthApp_BlazorApp\MyTemplate.vstemplate
      </ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="Vista.Biz" CopyParameters="true">
        SKBEarthApp_Vista.Biz\MyTemplate.vstemplate
      </ProjectTemplateLink>
      <ProjectTemplateLink ProjectName="Vista.DB" CopyParameters="true">
        SKBEarthApp_Vista.DB\MyTemplate.vstemplate
      </ProjectTemplateLink>
    </ProjectCollection>
  </TemplateContent>
</VSTemplate>

多專案(子)專案範本

SKBEarthApp_BlazorApp\MyTemplate.vstemplate
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <!-- (子)專案範本的基本資料。 -->
    <Name>SKBEarthApp_BlazorApp</Name>
    <Description>新光新地球應用系統,相依 Vista.Biz、Vista.DB。</Description>
    <ProjectType>Web</ProjectType>
    <ProjectSubType>CSharp</ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>SKBEarthApp_BlazorApp</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <CreateInPlace>true</CreateInPlace>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <!-- 以下是(子)專案範本原始碼或資源檔清單 -->
    <Project TargetFileName="SKBAPP.csproj" File="SKBAPP.csproj" ReplaceParameters="true">
      <Folder Name="Pages" TargetFolderName="Pages">
        <ProjectItem ReplaceParameters="true" TargetFileName="_Host.cshtml">_Host.cshtml</ProjectItem>
        <ProjectItem ReplaceParameters="false" TargetFileName="Index.razor">Index.razor</ProjectItem>
        <ProjectItem ReplaceParameters="false" TargetFileName="Index.razor.css">Index.razor.css</ProjectItem>
      </Folder>
      <ProjectItem ReplaceParameters="true" TargetFileName="_Imports.razor">_Imports.razor</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="App.razor">App.razor</ProjectItem>
      <ProjectItem ReplaceParameters="true" TargetFileName="appsettings.json">appsettings.json</ProjectItem>
      <ProjectItem ReplaceParameters="true" TargetFileName="appsettings.Development.json">appsettings.Development.json</ProjectItem>
      <ProjectItem ReplaceParameters="true" TargetFileName="Program.cs">Program.cs</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="ReadMe.txt">ReadMe.txt</ProjectItem>
    </Project>
  </TemplateContent>
</VSTemplate>
SKBEarthApp_Vista.Biz\MyTemplate.vstemplate
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <!-- (子)專案範本的基本資料。 -->
    <Name>SKBEarthApp_Vista.Biz</Name>
    <Description>新光新地球應用系統之 Vista.Biz,相依 Vista.DB。</Description>
    <ProjectType>CSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>SKBEarthApp_Vista.Biz</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <CreateInPlace>true</CreateInPlace>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <!-- 以下是(子)專案範本原始碼或資源檔清單 -->
    <Project TargetFileName="Vista.Biz.csproj" File="Vista.Biz.csproj" ReplaceParameters="true">
      <Folder Name="DEMO" TargetFolderName="DEMO">
        <ProjectItem ReplaceParameters="true" TargetFileName="SampleBiz.cs">SampleBiz.cs</ProjectItem>
      </Folder>
      <ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="ReadMe.txt">ReadMe.txt</ProjectItem>
      <ProjectItem ReplaceParameters="true" TargetFileName="SecBiz.cs">SecBiz.cs</ProjectItem>
    </Project>
  </TemplateContent>
</VSTemplate>
SKBEarthApp_Vista.DB\MyTemplate.vstemplate
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
  <TemplateData>
    <!-- (子)專案範本的基本資料。 -->
    <Name>SKBEarthApp_Vista.DB</Name>
    <Description>新光新地球應用系統之 Vista.DB</Description>
    <ProjectType>CSharp</ProjectType>
    <ProjectSubType>
    </ProjectSubType>
    <SortOrder>1000</SortOrder>
    <CreateNewFolder>true</CreateNewFolder>
    <DefaultName>SKBEarthApp_Vista.DB</DefaultName>
    <ProvideDefaultName>true</ProvideDefaultName>
    <LocationField>Enabled</LocationField>
    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>
    <CreateInPlace>true</CreateInPlace>
    <Icon>__TemplateIcon.ico</Icon>
  </TemplateData>
  <TemplateContent>
    <!-- 以下是(子)專案範本原始碼或資源檔清單 -->
    <Project TargetFileName="Vista.DB.csproj" File="Vista.DB.csproj" ReplaceParameters="true">
      <Folder Name="Schema" TargetFolderName="Schema">
        <ProjectItem ReplaceParameters="true" TargetFileName="UserLoginLog.cs">UserLoginLog.cs</ProjectItem>
      </Folder>
      <ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
      <ProjectItem ReplaceParameters="false" TargetFileName="ReadMe.txt">ReadMe.txt</ProjectItem>      
    </Project>
  </TemplateContent>
</VSTemplate>

參考文章

Last updated