English | 简体中文
A powerful source generator that injects code regions from template files into partial classes at compile time.
- 📁 Template-based code injection - Extract code regions from template files
- 🔄 Placeholder replacement - Replace placeholders with custom values
- 🎯 Multi-attribute support - Apply multiple injections to a single class
- 🏗️ Nested region support - Handle nested
#regionblocks correctly - ⚡ Incremental generation - Efficient compilation with minimal rebuilds
Install the package via NuGet Package Manager:
dotnet add package CodeInjectOr via Package Manager Console:
Install-Package CodeInjectCreate a template file and add it as an AdditionalFiles item in your project:
<ItemGroup> <AdditionalFilesInclude="Templates/ApiTemplate.cs" /> </ItemGroup>Template file content:
#region ApiMethods publicasyncTask<{ReturnType}>Get{EntityName}Async(intid){// Implementation herereturnawait_repository.GetByIdAsync<{ReturnType}>(id);}publicasyncTask<{ReturnType}>Create{EntityName}Async({ReturnType} entity){// Implementation herereturnawait_repository.CreateAsync(entity);} #endregionusingCodeInject;[RegionInject(FileName="Templates/ApiTemplate.cs",RegionName="ApiMethods",Placeholders=new[]{"ReturnType","User","EntityName","User"})]publicpartialclassUserService{privatereadonlyIRepository_repository;publicUserService(IRepositoryrepository){_repository=repository;}// Generated methods will be injected here automatically}The source generator will automatically create:
partialclassUserService{publicasyncTask<User>GetUserAsync(intid){// Implementation herereturnawait_repository.GetByIdAsync<User>(id);}publicasyncTask<User>CreateUserAsync(Userentity){// Implementation herereturnawait_repository.CreateAsync(entity);}}[RegionInject(FileName="Templates/CrudTemplate.cs",RegionName="CreateMethods",Placeholders=new[]{"Entity","Product"})][RegionInject(FileName="Templates/CrudTemplate.cs",RegionName="UpdateMethods",Placeholders=new[]{"Entity","Product"})][RegionInject(FileName="Templates/ValidationTemplate.cs",RegionName="Validators",Placeholders=new[]{"Type","Product"})]publicpartialclassProductService{// Multiple code regions will be injected}If you don't specify the FileName, the generator will search all available files for the specified region:
[RegionInject(RegionName="CommonMethods")]publicpartialclassBaseService{// Generator will search all files for "CommonMethods" region}[RegionInject(FileName="Templates/ApiTemplate.cs",RegionName="ApiMethods",Placeholders=new[]{"ReturnType","Order","EntityName","Order"})]publicpartialclassOrderService{// Generated code with Order-specific implementations}Add template files to your project as AdditionalFiles:
<ItemGroup> <AdditionalFilesInclude="Templates/**/*.cs" /> <AdditionalFilesInclude="CodeTemplates/**/*.txt" /> </ItemGroup>- Use
#region RegionNameand#endregionto define code blocks - Support for nested regions
- Placeholders can be used in two formats:
{PlaceholderName}- with curly bracesPlaceholderName- without braces
// Templates/ControllerTemplate.cs #region CrudActions [HttpGet]publicasyncTask<ActionResult<IEnumerable<{EntityType}>>>Get{EntityName}s(){ var items =await _{entityName}Service.GetAllAsync();return Ok(items);}[HttpGet("{id}")] public async Task<ActionResult<{EntityType}>> Get{EntityName}(int id){ var item =await _{entityName}Service.GetByIdAsync(id);return item ==null? NotFound(): Ok(item);}[HttpPost] public async Task<ActionResult<{EntityType}>> Create{EntityName}({EntityType}{entityName}){ var created =await _{entityName}Service.CreateAsync({entityName});return CreatedAtAction(nameof(Get{EntityName}),new{ id = created.Id }, created);} #endregionUsage:
[RegionInject(FileName="Templates/ControllerTemplate.cs",RegionName="CrudActions",Placeholders=new[]{"EntityType","Product","EntityName","Product","entityName","product"})]publicpartialclassProductController:ControllerBase{// Generated CRUD actions will be injected here}// Templates/RepositoryTemplate.cs #region RepositoryMethods publicasyncTask<IEnumerable<{EntityType}>>GetAll{EntityName}sAsync(){returnawait_context.{EntityName}s.ToListAsync();} public async Task<{EntityType}> Get{EntityName}ByIdAsync(intid){returnawait_context.{EntityName}s.FindAsync(id);} public async Task<{EntityType}>Create{EntityName}Async({EntityType}entity){_context.{EntityName}s.Add(entity);await_context.SaveChangesAsync();returnentity;} #endregionUsage:
[RegionInject(FileName="Templates/RepositoryTemplate.cs",RegionName="RepositoryMethods",Placeholders=new[]{"EntityType","User","EntityName","User"})]publicpartialclassUserRepository{// Generated repository methods will be injected here}The source generator provides the following diagnostic information:
- CRG001: Template file not found
- CRG002: Region not found
- CRG003: File read error
- Organize templates: Keep template files in a dedicated
Templatesfolder - Naming conventions: Use descriptive region names like
CrudMethods,ValidationRules - Placeholder naming: Use consistent placeholder names like
EntityType,EntityName - Modularization: Group related functionality into different regions
- Property-based syntax: Use the new property-based initialization for better readability
- .NET Standard 2.0 or higher
- C# 7.3 or higher
- Visual Studio 2019 16.9+ or .NET 5.0+ SDK
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
| Feature | CodeInject | T4 Templates | Manual Coding |
|---|---|---|---|
| Compile-time generation | ✅ | ❌ | ❌ |
| Incremental compilation | ✅ | ❌ | ✅ |
| IDE support | ✅ | ✅ | |
| Learning curve | Low | High | Low |
| Flexibility | High | High | Low |
If you encounter any issues:
- Check the FAQ
- Search existing issues
- Create a new issue
⭐ If this project helps you, please give it a star!