在ASP.NET Core中引入了DI,並且通過構造函數注入參數,控制器中會大量使用DI注入各種的配置參數,如果配置注入的參數比較多,而且各個控制器需要的配置參數都基本一樣的話,那麼不斷重復的復制黏貼代碼提供相應的構造函數,效率低效也,因此使用T4模板生成控制器的構造函數 ,這也得益於C#對分部類(partial)的支持。
圖中CtrlTemplate.tt為模板文件,CtrlNames.txt為需要使用T4生成代碼的控制器名稱文件,CtrlTemplate.cs為T4模板生成的文件。
CtrlNames.txt文件內容:
Values Account
CtrlTemplate.tt代碼:
1 <#@ template language="C#" debug="false" hostspecific="true"#> 2 <#@ assembly name="System.Core" #> 3 <#@ import namespace="System.Linq" #> 4 <#@ import namespace="System.Text" #> 5 <#@ import namespace="System.Collections.Generic" #> 6 <#@ output extension=".cs" #> 7 using ApiCoreTest; 8 using EFDbContext; 9 using Microsoft.AspNetCore.Mvc; 10 using Microsoft.Extensions.Logging; 11 using Microsoft.Extensions.Options; 12 13 namespace ApiCoreTest.Controllers 14 { 15 <# 16 //獲取項目的根目錄 17 var solutionsPath = Host.ResolveAssemblyReference("$(SolutionDir)"); 18 //獲取配置文件 19 var lines = System.IO.File.ReadAllLines(solutionsPath + @"/src/ApiCoreTest/Controllers/Template/CtrlNames.txt"); 20 foreach(var name in lines) 21 {#> 22 public partial class <#= name#>Controller : Controller 23 { 24 IOptions<ConfigModel> _config; 25 ILogger<<#= name#>Controller> _logger; 26 ApplicationDbContext _db; 27 public <#= name#>Controller(IOptions<ConfigModel> config, ILogger<<#= name#>Controller> logger, ApplicationDbContext db) 28 { 29 _config = config; 30 _logger = logger; 31 _db = db; 32 } 33 } 34 <#}#> 35 }
模板生成的文件CtrlTemplate.cs 內容:
1 using ApiCoreTest; 2 using EFDbContext; 3 using Microsoft.AspNetCore.Mvc; 4 using Microsoft.Extensions.Logging; 5 using Microsoft.Extensions.Options; 6 7 namespace ApiCoreTest.Controllers 8 { 9 public partial class ValuesController : Controller 10 { 11 IOptions<ConfigModel> _config; 12 ILogger<ValuesController> _logger; 13 ApplicationDbContext _db; 14 public ValuesController(IOptions<ConfigModel> config, ILogger<ValuesController> logger, ApplicationDbContext db) 15 { 16 _config = config; 17 _logger = logger; 18 _db = db; 19 } 20 } 21 public partial class AccountController : Controller 22 { 23 IOptions<ConfigModel> _config; 24 ILogger<AccountController> _logger; 25 ApplicationDbContext _db; 26 public AccountController(IOptions<ConfigModel> config, ILogger<AccountController> logger, ApplicationDbContext db) 27 { 28 _config = config; 29 _logger = logger; 30 _db = db; 31 } 32 } 33 }
使用了模板的控制器:
1 namespace ApiCoreTest.Controllers 2 { 3 [Route("api/[controller]")] 4 public partial class ValuesController : Controller 5 { 6 [HttpGet] 7 public string Gets() 8 { 9 var val = JsonConvert.SerializeObject(_config.Value); 10 _logger.LogDebug(val); 11 return val; 12 } 13 } 14 }
1 namespace ApiCoreTest.Controllers 2 { 3 public partial class AccountController : Controller 4 { 5 public IActionResult Test() 6 { 7 var val = JsonConvert.SerializeObject(_config.Value); 8 _logger.LogDebug(val); 9 return Content(val); 10 } 11 } 12 }
使用了T4模板的控制器必須設置為分部類,而且命名空間要一致。