TypedPaths.Generator 1.2.8

There is a newer version of this package available.
See the version list below for details.
dotnet add package TypedPaths.Generator --version 1.2.8
                    
NuGet\Install-Package TypedPaths.Generator -Version 1.2.8
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TypedPaths.Generator" Version="1.2.8" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TypedPaths.Generator" Version="1.2.8" />
                    
Directory.Packages.props
<PackageReference Include="TypedPaths.Generator" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TypedPaths.Generator --version 1.2.8
                    
#r "nuget: TypedPaths.Generator, 1.2.8"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TypedPaths.Generator@1.2.8
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TypedPaths.Generator&version=1.2.8
                    
Install as a Cake Addin
#tool nuget:?package=TypedPaths.Generator&version=1.2.8
                    
Install as a Cake Tool

TypedPaths.Generator

A Roslyn source generator that turns configured folder trees into strongly typed path constants at compile time. Each configured folder becomes a nested static class (for example Src, Template) so you can avoid magic strings.

What you get

Given a structure like:

/src
  Template1.anyext
  folderA/
    Template2.anyext
  folderB/
    Template3.anyext
    Template4.anyext
/template
  email/
    welcome.txt
  sms/
    otp.txt

the generator emits one file per root folder (TypedPaths.Src.g.cs, TypedPaths.Template.g.cs, ...), each contributing to the same partial root class:

// TypedPaths.Src.g.cs
// <auto-generated/>
namespace TypedPaths;

public static partial class TypedPaths
{
    public static partial class Src
    {
        public const string Value = "src";

        public static partial class Template1
        {
            public const string Value = "src/Template1.anyext";
        }

        public static partial class FolderA
        {
            public const string Value = "src/folderA";

            public static partial class Template2
            {
                public const string Value = "src/folderA/Template2.anyext";
            }
        }

        public static partial class FolderB
        {
            public const string Value = "src/folderB";

            public static partial class Template3
            {
                public const string Value = "src/folderB/Template3.anyext";
            }

            public static partial class Template4
            {
                public const string Value = "src/folderB/Template4.anyext";
            }
        }
    }
}
// TypedPaths.Template.g.cs
// <auto-generated/>
namespace TypedPaths;

public static partial class TypedPaths
{
    public static partial class Template
    {
        public const string Value = "template";

        public static partial class Email
        {
            public const string Value = "template/email";

            public static partial class Welcome
            {
                public const string Value = "template/email/welcome.txt";
            }
        }

        public static partial class Sms
        {
            public const string Value = "template/sms";

            public static partial class Otp
            {
                public const string Value = "template/sms/otp.txt";
            }
        }
    }
}

So you can use TypedPaths.Src.FolderA.Template2.Value and TypedPaths.Template.Email.Welcome.Value instead of raw string paths.

Requirements

  • .NET 8 (or the TFM your project uses; the generator targets .NET Standard 2.0)
  • MSBuild / SDK-style projects

Setup

<ItemGroup>
  <PackageReference Include="TypedPaths.Generator" Version="1.0.0" />
</ItemGroup>

<ItemGroup>
  <TypedPathsFolder Include="src" ClassName="Src" />
  <TypedPathsFolder Include="template" />
</ItemGroup>

That is the only configuration needed in consumer projects.
TypedPaths.Generator.targets (from package build) automatically maps each TypedPathsFolder to AdditionalFiles for source generation.

Option B: local project reference (repository development)

<ItemGroup>
  <ProjectReference Include="..\TypedPaths.Generator\TypedPaths.Generator.csproj"
                    OutputItemType="Analyzer"
                    ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
  <TypedPathsFolder Include="src" ClassName="Src" />
  <TypedPathsFolder Include="template" />
</ItemGroup>

<Import Project="..\TypedPaths.Generator\build\TypedPaths.Generator.targets"
        Condition="Exists('..\TypedPaths.Generator\build\TypedPaths.Generator.targets')" />

The explicit <Import /> is required only for local project-reference scenarios.

Build the project; the generator runs and adds TypedPaths.*.g.cs files to the compilation.

Usage in code

The generated type is in namespace TypedPaths, and the root class is also named TypedPaths. To avoid name clashes, use an alias:

using TypedPathsRoot = TypedPaths.TypedPaths;

// Always read .Value (works for both folder and file nodes)
string folderPath = TypedPathsRoot.Src.FolderA.Value; // "src/folderA"
string filePath = TypedPathsRoot.Src.FolderA.Template2.Value;  // "src/folderA/Template2.anyext"
string emailTemplate = TypedPathsRoot.Template.Email.Welcome.Value; // "template/email/welcome.txt"

// e.g. resolve to full path
var fullPath = Path.Combine(projectRoot, TypedPathsRoot.Src.FolderA.Template2.Value);

Value is always a path relative to the project root:

  • Folder node Value = relative folder path
  • File node Value = relative file path (including extension)

Nested child classes are emitted only for folders (because only folders can contain files/subfolders).

Naming rules

  • Folder and file names become PascalCase identifiers.
  • Invalid identifier characters are dropped or split; leading digits get a _ prefix.
  • Duplicate names in the same scope get suffixes: _2, _3, etc.
  • Extensions are stripped from member names but kept in the path string.
  • If a folder name and file name conflict in the same scope:
    • the folder keeps the base name;
    • the file name becomes FileName + ExtensionWithoutDot (example: report/ + report.txtReport and ReportTxt);
    • if the conflicting file has no extension, use File suffix (example: data/ + dataData and DataFile).

Repository layout

Project Description
TypedPaths.Generator The source generator (Roslyn incremental generator).
TypedPaths.Generator.Sample Example app that uses the generator and runs a small demo.
TypedPaths.Generator.Tests Unit tests for the generator.

Build and test

dotnet restore
dotnet build
dotnet test

Run the sample:

dotnet run --project TypedPaths.Generator.Sample

License

See the repository for license information.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 105 3/4/2026
1.2.9 90 3/3/2026
1.2.8 91 3/3/2026
1.2.7 95 3/3/2026
1.2.6 95 3/3/2026
1.2.5 94 3/3/2026
1.2.4 97 3/3/2026
1.2.1 97 3/3/2026
1.2.0 100 3/3/2026
1.1.0 104 3/2/2026
1.0.0 106 3/2/2026