Maestria.TypeProviders by Fábio Monteiro Naspolini
NuGet / site data
Details
Info
Name: Maestria.TypeProviders
.NET 5 C# Source TypeProviders.
Author: Fábio Monteiro Naspolini
NuGet: https://www.nuget.org/packages/Maestria.TypeProviders/
You can find more details at https://github.com/MaestriaNet/TypeProviders
Author
Fábio Monteiro Naspolini

Original Readme
Maestria.TypeProviders
If my contributions helped you, please help me buy a coffee :D
What is Maestria.Type.Providers?
Source Generator pack to increase productivity and improve source code writing.
How install and configure package?
First, install Maestria.Type.Providers from the dotnet cli command line:
dotnet add package Maestria.TypeProviders
dotnet add package ClosedXML
Providers x Dependencies
This package does not include dependencies references when installed on your project, its only generate source code files.
You need install thirds dependencies to compile your project according to the features used, bellow instructions of source generator providers:
- ExcelProvider: Generated strong data sctruct and factory class to load xls/xlsx data.
- OpenApiProvider: Generate HTTP client from OpenApi / Swagger specification.
ExcelProvider
Generate strong data struct and class factory to load excel data from xls/xlsx template.
Attribute: ExcelProvider
Dependencies
- ClosedXML: v0.105.0+
Dependencies install
dotnet add package ClosedXML
Use case sample
// The relative path is based at the source code file location.
// In this example the first page was used as none were explicitly entered.
[ExcelProvider(TemplatePath = @"../../resources/Excel.xlsx")]
public partial class MyExcelData
{
}
var data = MyExcelDataFactory.Load(filePath);
foreach (var item in data)
// Access strong typing by "item.<field-name>"
Use case sample two
// The relative path is based at the source code file location.
// Loadind data struct from second page
[ExcelProvider(TemplatePath = @"../../resources/Excel.xlsx", SheetName = "Plan2")]
public partial class MyExcelData
{
}
var data = MyExcelDataFactory.Load(filePath, "Plan2");
foreach (var item in data)
// Access strong typing by "item.<field-name>"
Generator engine:
Nullable types: To create a nullable property, seed excel template file with one row cell empty, and another not empty.Decimal types: To create decimal property, seed one row of cell with floating point value.
Good practices: Don't use big file by template, this file is used always you need recreated source code. Big file impact is slow build time.
OpenApiProvider
Provider to generate source code HTTP client from OpenApi / Swagger specification.
It's planned used NSwagStudio engine with .NET 5 source generator.
This package allows automatized generation code.
...As soon as possible
Troubleshooting
Optional configuration in VS Code: To view the automatically generated codes it is necessary to indicate to write it to disk with the configuration in the .csproj file.
On CompilerGeneratedFilesOutputPath property its configured with /../generated/$(MSBuildProjectName). This folder is one level above of file project on this sample.
This mode allow see generated files, but not works go to navigation feature of VS Code.
<!-- Enable source disk file write to correct IDE's works -->
<PropertyGroup>
<CompilerGeneratedFilesOutputPath>$(MSBuildProjectDirectory)/../generated/$(MSBuildProjectName)</CompilerGeneratedFilesOutputPath>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
Optional configuration in VS Code: To allow go to navigation feature you need write files at solution level.
Problem's: The source code generated will be used on next build, to solve problems of duplicated classes, it's need removed generated files before build.
On next build, if there was no change on yout source code used by generators, the files has no generated. You need force a rebuild withdotnet build --no-incremental <args>to regenerate files.
<!-- Enable source disk file write to correct IDE's works -->
<PropertyGroup>
<CompilerGeneratedFilesOutputPath>$(MSBuildProjectDirectory)/generated/$(MSBuildProjectName)</CompilerGeneratedFilesOutputPath>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
</PropertyGroup>
<!-- Remove files on build start to solve recreate bug message "alwaready exists" -->
<Target Name="ExcludeGenerated" BeforeTargets="AssignTargetPaths">
<ItemGroup>
<Generated Include="/generated/**/*.cs" />
<Compile Remove="@(Generated)" />
</ItemGroup>
<Delete Files="@(Generated)" />
</Target>
4 devs
Restart build server to validate clean source generator build.
dotnet build-server shutdown
If my contributions helped you, please help me buy a coffee :D
About
Generating strong typed code from Excel.
How to use
Example (source csproj, source files)
- CSharp Project
- Program.cs
- MyExcelPerson.cs
- Person.cs
This is the CSharp Project that references Maestria.TypeProviders
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.105.0" />
<PackageReference Include="Maestria.Extensions" Version="3.7.2.0" />
<PackageReference Include="Maestria.TypeProviders" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<None Update="MyExcel.xlsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>
</Project>
This is the use of Maestria.TypeProviders in Program.cs
using DemoExcel;
Console.WriteLine("Hello, World!");
var persons = MyExcelPersonFactory.Load("MyExcel.xlsx").ToArray();
foreach (var person in persons)
{
Console.WriteLine(person.ID + person.FullName());
}
This is the use of Maestria.TypeProviders in MyExcelPerson.cs
namespace DemoExcel;
public partial class MyExcelPerson
{
public string FullName() => $"{FirstName} {LastName}";
}
This is the use of Maestria.TypeProviders in Person.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace DemoExcel;
[ExcelProvider(TemplatePath = @"MyExcel.xlsx")]
public partial class MyExcelPerson
{
}
Generated Files
Those are taken from $(BaseIntermediateOutputPath)\GX
- DemoExcel.MyExcelPerson.g.cs
- ExcelExtensions.g.cs
- ExcelGeneratorException.g.cs
- ExcelProviderAttribute.g.cs
//----------------------
// <auto-generated>
// Generated using Maestria.TypeProviders (https://github.com/MaestriaNet/TypeProviders)
// </auto-generated>
//----------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using ClosedXML.Excel;
using Maestria.TypeProviders.Excel;
namespace DemoExcel
{
public partial class MyExcelPerson
{
public int ID \{ get; set; }
public string FirstName \{ get; set; }
public string LastName \{ get; set; }
}
public static partial class MyExcelPersonFactory
{
public static IEnumerable<MyExcelPerson> Load(Stream input, int sheetPosition = 1)
{
using var workbook = new XLWorkbook(input);
return Load(workbook, sheetPosition, null);
}
public static IEnumerable<MyExcelPerson> Load(Stream input, string sheetName)
{
using var workbook = new XLWorkbook(input);
return Load(workbook, 0, sheetName);
}
public static IEnumerable<MyExcelPerson> Load(string filePath, int sheetPosition = 1)
{
using var workbook = ExcelExtensions.OpenWorkbook(filePath);
return Load(workbook, sheetPosition, null);
}
public static IEnumerable<MyExcelPerson> Load(string filePath, string sheetName)
{
using var workbook = ExcelExtensions.OpenWorkbook(filePath);
return Load(workbook, 0, sheetName);
}
public static IEnumerable<MyExcelPerson> Load(XLWorkbook workbook, int sheetPosition = 1, string sheetName = "")
{
var result = new List<MyExcelPerson>();
var sheet = string.IsNullOrEmpty(sheetName) ? workbook.Worksheet(sheetPosition) : workbook.Worksheet(sheetName);
var indexOfID = sheet.ColumnByName(@"ID");
var indexOfFirstName = sheet.ColumnByName(@"FirstName");
var indexOfLastName = sheet.ColumnByName(@"LastName");
foreach (var row in sheet.Rows(2, sheet.RowUsedCount()))
{
var iDValue = row.Cell(indexOfID);
var firstNameValue = row.Cell(indexOfFirstName);
var lastNameValue = row.Cell(indexOfLastName);
result.Add(new MyExcelPerson
{
ID = iDValue.GetValue<int>(),
FirstName = firstNameValue.GetValue<string>(),
LastName = lastNameValue.GetValue<string>(),
});
}
return result;
}
}
}
//----------------------
// <auto-generated>
// Generated using Maestria.TypeProviders (https://github.com/MaestriaNet/TypeProviders)
// </auto-generated>
//----------------------
using System;
using System.IO;
using ClosedXML.Excel;
namespace Maestria.TypeProviders.Excel;
public static class ExcelExtensions
{
/// <summary>
/// Number of last user column
/// </summary>
/// <param name="sheet"></param>
/// <returns></returns>
public static int ColumnUsedCount(this IXLWorksheet sheet) => sheet.LastColumnUsed().ColumnNumber();
/// <summary>
/// Number of last used row
/// </summary>
/// <param name="sheet"></param>
/// <returns></returns>
public static int RowUsedCount(this IXLWorksheet sheet) => sheet.LastRowUsed().RowNumber();
/// <summary>
/// Retrieve column position by name in first row.
/// </summary>
/// <param name="sheet">Page to find column</param>
/// <param name="columnName">Name to find column in first row</param>
/// <returns>Position of column name or 0 when not found</returns>
/// <exception cref="ArgumentNullException">When <paramref name="columnName"/> is null o whitespace</exception>
public static int ColumnByName(this IXLWorksheet sheet, string columnName)
{
if (string.IsNullOrWhiteSpace(columnName)) throw new ExcelArgumentNullException(nameof(columnName), "Enter the column name to get position.");
if (sheet.RowCount() <= 0)
return 0;
for (var i = 1; i <= sheet.ColumnUsedCount(); i++)
if (sheet.Row(1).Cell(i).Value.ToString()?.ToUpper() == columnName.ToUpper()) return i;
return 0;
}
/// <summary>
/// Open file with treatment for file in use by another process
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static FileStream OpenFile(string filePath)
{
try
{
return new FileStream(filePath, FileMode.Open, FileAccess.Read);
}
catch
{
// Need more access permissions to the file already in use by the operating system
return new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
}
}
/// <summary>
/// Open file with treatment for file in use by another process and return XLWorkbook
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public static XLWorkbook OpenWorkbook(string filePath)
{
using var fileStream = OpenFile(filePath);
return new XLWorkbook(fileStream);
}
}
using System;
namespace Maestria.TypeProviders.Excel;
internal class ExcelGeneratorException : Exception
{
public ExcelGeneratorException()
{
}
public ExcelGeneratorException(string message) : base(message)
{
}
public ExcelGeneratorException(string message, Exception innerException) : base(message, innerException)
{
}
}
internal class ExcelArgumentOutOfRangeException : ArgumentOutOfRangeException
{
public ExcelArgumentOutOfRangeException()
{
}
public ExcelArgumentOutOfRangeException(string paramName) : base(paramName)
{
}
public ExcelArgumentOutOfRangeException(string message, Exception innerException) : base(message, innerException)
{
}
public ExcelArgumentOutOfRangeException(string paramName, object actualValue, string message) : base(paramName, actualValue, message)
{
}
public ExcelArgumentOutOfRangeException(string paramName, string message) : base(paramName, message)
{
}
}
internal class ExcelArgumentNullException : ArgumentNullException
{
public ExcelArgumentNullException()
{
}
public ExcelArgumentNullException(string paramName) : base(paramName)
{
}
public ExcelArgumentNullException(string message, Exception innerException) : base(message, innerException)
{
}
public ExcelArgumentNullException(string paramName, string message) : base(paramName, message)
{
}
}
//----------------------
// <auto-generated>
// Generated using Maestria.TypeProviders (https://github.com/MaestriaNet/TypeProviders)
// </auto-generated>
//----------------------
using System;
/// <summary>
/// Map excel file and auto generate DTO and Factory classes
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ExcelProviderAttribute : Attribute
{
public const string TypeFullName = "ExcelProviderAttribute";
/// <summary>
/// <para>
/// File path to load Excel template and generate source code.
/// </para>
/// <para>
/// It's supported relative path with format "..\..\folder\file.xlsx".
/// The relative path is based at the source code file location.
/// </para>
/// </summary>
public string TemplatePath \{ get; set; }
/// <summary>
/// Sheet position to build classes. Stated from 1.
/// </summary>
public int SheetPosition \{ get; set; \} = 1;
/// <summary>
/// Sheet name to build classes.
/// </summary>
public string SheetName \{ get; set; }
}
Useful
Download Example (.NET C#)
Share Maestria.TypeProviders
https://ignatandrei.github.io/RSCG_Examples/v2/docs/Maestria.TypeProviders
Category "FilesToCode" has the following generators:
1 Chorn.EmbeddedResourceAccessGenerator
2024-01-21
2 corecraft
2024-02-17
3 Datacute.EmbeddedResourcePropertyGenerator
2024-11-03
4 DotnetYang
2024-06-29
5 EmbedResourceCSharp
2023-04-16
6 kli.Localize
2025-10-01
7 LingoGen
2024-02-23
8 Maestria.TypeProviders
2026-04-09
9 NFH.FileEmbed
2025-08-08
10 NotNotAppSettings
2024-01-26
11 Podimo.ConstEmbed
2023-04-16
12 ResXGenerator
2023-10-02
13 RSCG_JSON2Class
2024-02-29
14 RSCG_Utils
2023-04-16
15 Strings.ResourceGenerator
2025-07-06
16 SvgIconGenerator
2026-04-04
17 ThisAssembly_Resources
2023-09-16
18 ThisAssembly.Strings
2024-07-21
19 TypedPaths
2026-04-01
20 Weave
2024-01-27


