Nextended.CodeGen

Compile-time source code generation from various sources including classes, JSON, XML, and Excel files.

Overview

Nextended.CodeGen is a Roslyn source generator that automatically generates code at compile-time. It supports DTO generation from attributes, class generation from JSON/XML structures, and model generation from Excel spreadsheets.

Note: This package is in early testing stage. The API may change in future releases.

Installation

dotnet add package Nextended.CodeGen
dotnet add package Nextended.Core

Key Features

1. DTO Generation from Attributes

Automatically generate Data Transfer Objects (DTOs) from your domain classes.

using Nextended.Core.Attributes;

[AutoGenerateDto(
    ToDtoMethodName = "ToDto",
    ToSourceMethodName = "ToEntity",
    IsComCompatible = true,
    Namespace = "MyApp.Dtos"
)]
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public string Password { get; set; } // Can be excluded in DTO
}

Generated DTO:

namespace MyApp.Dtos
{
    public class UserDto
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
    }
}

2. Class Generation from JSON/XML

Generate strongly-typed classes from configuration files or API responses.

// appsettings.json
{
  "Database": {
    "ConnectionString": "Server=localhost;...",
    "MaxPoolSize": 100
  },
  "Api": {
    "BaseUrl": "https://api.example.com",
    "Timeout": 30
  }
}

Configuration:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/appsettings.json",
      "RootClassName": "ServerConfiguration",
      "Namespace": "MyApp.Configuration"
    }
  ]
}

Generated class:

namespace MyApp.Configuration
{
    public class ServerConfiguration
    {
        public Database Database { get; set; }
        public Api Api { get; set; }
    }
    
    public class Database
    {
        public string ConnectionString { get; set; }
        public int MaxPoolSize { get; set; }
    }
    
    public class Api
    {
        public string BaseUrl { get; set; }
        public int Timeout { get; set; }
    }
}

3. Excel to Class Generation

Generate data classes and static lookup tables from Excel spreadsheets.

{
  "ExcelGenerations": [
    {
      "ModelType": "RecordStruct",
      "SourceFile": "/Sources/countries.xlsx",
      "Namespace": "MyApp.Data",
      "RootClassName": "Country",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "GenerateModelClass": true,
      "GenerateStaticTable": true,
      "StaticClassName": "Countries",
      "GenerateAllCollection": true
    }
  ]
}

Configuration

Project Setup

  1. Add packages to your .csproj:
<ItemGroup>
  <PackageReference Include="Nextended.CodeGen" Version="9.0.15" />
  <PackageReference Include="Nextended.Core" Version="9.0.15" PrivateAssets="all" GeneratePathProperty="true" />
</ItemGroup>
  1. Create CodeGen.config.json:
{
  "DtoGeneration": {
    "ComIdClassName": "ComGuids",
    "ComIdClassPropertyFormat": "Id{0}",
    "ComIdClassModifier": "Public",
    "OneFilePerClass": true,
    "CreateRegions": true,
    "CreateComments": true,
    "GeneratePartial": true,
    "Namespace": "MyApp.Generated",
    "Suffix": "Dto"
  },
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/appsettings.json",
      "RootClassName": "AppSettings",
      "Namespace": "MyApp.Configuration"
    }
  ]
}
  1. Add config file to .csproj:
<ItemGroup>
  <AdditionalFiles Include="CodeGen.config.json" />
</ItemGroup>

Usage Examples

Basic DTO Generation

using Nextended.Core.Attributes;

[AutoGenerateDto]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
    public DateTime CreatedDate { get; set; }
}

// Usage after build
var product = new Product 
{ 
    Id = 1, 
    Name = "Widget", 
    Price = 99.99m 
};

var dto = product.ToDto(); // Generated extension method
var backToEntity = dto.ToEntity(); // Round-trip conversion

Advanced DTO Configuration

[AutoGenerateDto(
    Suffix = "Dto",
    Prefix = null,
    ToDtoMethodName = "ToTransferObject",
    ToSourceMethodName = "ToModel",
    Namespace = "MyApp.Dtos",
    IsComCompatible = true,
    GeneratePartial = true
)]
public class Order
{
    public int Id { get; set; }
    public string OrderNumber { get; set; }
    public List<OrderItem> Items { get; set; }
    public Customer Customer { get; set; }
    
    [IgnoreInDto]
    public string InternalNotes { get; set; }
}

Configuration from JSON

appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning"
    }
  },
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=MyDb;..."
  },
  "Features": {
    "EnableCache": true,
    "MaxRetries": 3
  }
}

CodeGen.config.json:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/appsettings.json",
      "RootClassName": "AppConfiguration",
      "Namespace": "MyApp.Config",
      "Ignore": ["Logging.LogLevel.Microsoft"]
    }
  ]
}

Usage:

var config = new AppConfiguration();
var connectionString = config.ConnectionStrings.DefaultConnection;

Excel Data Generation

Excel file structure: | Code | Name | Country | Active | |——|——|———|——–| | US | United States | USA | Yes | | UK | United Kingdom | GBR | Yes | | CA | Canada | CAN | Yes |

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Sources/locations.xlsx",
      "Namespace": "MyApp.Data",
      "RootClassName": "Location",
      "KeyColumn": "A",
      "StaticClassName": "Locations",
      "GenerateStaticTable": true,
      "ColumnMappings": {
        "Code": "LocationCode",
        "Name": "LocationName"
      }
    }
  ]
}

Generated code:

public record struct Location
{
    public string LocationCode { get; init; }
    public string LocationName { get; init; }
    public string Country { get; init; }
    public string Active { get; init; }
}

public static class Locations
{
    public static Location US => new() 
    { 
        LocationCode = "US", 
        LocationName = "United States",
        Country = "USA",
        Active = "Yes"
    };
    
    public static Location UK => new() 
    { 
        LocationCode = "UK", 
        LocationName = "United Kingdom",
        Country = "GBR",
        Active = "Yes"
    };
    
    public static IReadOnlyList<Location> All { get; } = new[]
    {
        US, UK, CA
    };
}

Usage:

var usLocation = Locations.US;
var allLocations = Locations.All;

Detailed Generation Examples

JSON Structure Generation

Generate strongly-typed classes from JSON files such as configuration files, API responses, or data schemas.

Example 1: Application Configuration

Source File: appsettings.json

{
  "Database": {
    "ConnectionString": "Server=localhost;Database=MyApp;",
    "Timeout": 30,
    "MaxRetryCount": 3
  },
  "Redis": {
    "Host": "localhost",
    "Port": 6379,
    "DefaultDatabase": 0
  },
  "Security": {
    "JwtSecret": "your-secret-key",
    "TokenExpirationMinutes": 60,
    "EnableTwoFactor": true
  },
  "Features": {
    "EnableCache": true,
    "EnableLogging": true,
    "MaxUploadSizeMB": 10
  }
}

Configuration: CodeGen.config.json

{
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/appsettings.json",
      "RootClassName": "ApplicationSettings",
      "Namespace": "MyApp.Configuration",
      "Prefix": "App",
      "OutputPath": "./Generated/Configuration/"
    }
  ]
}

Generated Classes:

namespace MyApp.Configuration
{
    public class AppApplicationSettings
    {
        public Database Database { get; set; }
        public Redis Redis { get; set; }
        public Security Security { get; set; }
        public Features Features { get; set; }
    }

    public class Database
    {
        public string ConnectionString { get; set; }
        public int Timeout { get; set; }
        public int MaxRetryCount { get; set; }
    }

    public class Redis
    {
        public string Host { get; set; }
        public int Port { get; set; }
        public int DefaultDatabase { get; set; }
    }

    public class Security
    {
        public string JwtSecret { get; set; }
        public int TokenExpirationMinutes { get; set; }
        public bool EnableTwoFactor { get; set; }
    }

    public class Features
    {
        public bool EnableCache { get; set; }
        public bool EnableLogging { get; set; }
        public int MaxUploadSizeMB { get; set; }
    }
}

Usage:

using MyApp.Configuration;

// Use the generated strongly-typed configuration
var settings = new AppApplicationSettings
{
    Database = new Database 
    { 
        ConnectionString = "...",
        Timeout = 30 
    }
};

// Access with IntelliSense support
var timeout = settings.Database.Timeout;
var enableCache = settings.Features.EnableCache;

Example 2: API Response Schema

Source File: user-api-response.json

{
  "user": {
    "id": 123,
    "username": "john_doe",
    "email": "john@example.com",
    "profile": {
      "firstName": "John",
      "lastName": "Doe",
      "avatar": "https://example.com/avatar.jpg",
      "bio": "Software Developer"
    },
    "settings": {
      "notifications": {
        "email": true,
        "push": false,
        "sms": true
      },
      "privacy": {
        "profileVisible": true,
        "showEmail": false
      }
    },
    "metadata": {
      "createdAt": "2024-01-01T00:00:00Z",
      "lastLogin": "2024-06-15T10:30:00Z",
      "accountStatus": "active"
    }
  }
}

Configuration:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/user-api-response.json",
      "RootClassName": "UserApiResponse",
      "Namespace": "MyApp.ApiModels",
      "Ignore": ["metadata.lastLogin"]
    }
  ]
}

Generated Classes:

namespace MyApp.ApiModels
{
    public class UserApiResponse
    {
        public User User { get; set; }
    }

    public class User
    {
        public int Id { get; set; }
        public string Username { get; set; }
        public string Email { get; set; }
        public Profile Profile { get; set; }
        public Settings Settings { get; set; }
        public Metadata Metadata { get; set; }
    }

    public class Profile
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Avatar { get; set; }
        public string Bio { get; set; }
    }

    public class Settings
    {
        public Notifications Notifications { get; set; }
        public Privacy Privacy { get; set; }
    }

    public class Notifications
    {
        public bool Email { get; set; }
        public bool Push { get; set; }
        public bool Sms { get; set; }
    }

    public class Privacy
    {
        public bool ProfileVisible { get; set; }
        public bool ShowEmail { get; set; }
    }

    public class Metadata
    {
        public string CreatedAt { get; set; }
        public string AccountStatus { get; set; }
    }
}

XML Structure Generation

Generate classes from XML files using the same configuration structure.

Source File: config.xml

<?xml version="1.0" encoding="utf-8"?>
<Configuration>
  <Server>
    <Host>localhost</Host>
    <Port>8080</Port>
    <EnableSSL>true</EnableSSL>
  </Server>
  <Logging>
    <Level>Information</Level>
    <FilePath>./logs/app.log</FilePath>
    <MaxFileSizeMB>50</MaxFileSizeMB>
  </Logging>
</Configuration>

Configuration:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Sources/config.xml",
      "RootClassName": "ServerConfiguration",
      "Namespace": "MyApp.XmlConfig"
    }
  ]
}

Generated Classes:

namespace MyApp.XmlConfig
{
    public class ServerConfiguration
    {
        public Server Server { get; set; }
        public Logging Logging { get; set; }
    }

    public class Server
    {
        public string Host { get; set; }
        public int Port { get; set; }
        public bool EnableSSL { get; set; }
    }

    public class Logging
    {
        public string Level { get; set; }
        public string FilePath { get; set; }
        public int MaxFileSizeMB { get; set; }
    }
}

Excel Generation (Advanced)

Generate data models and static lookup tables from Excel spreadsheets. This is particularly useful for reference data, lookup tables, and configuration data.

Example 1: Country/Region Codes

Excel File Structure: countries.xlsx

Code Name ISO3 NumericCode PhonePrefix Capital
US United States USA 840 +1 Washington, D.C.
GB United Kingdom GBR 826 +44 London
DE Germany DEU 276 +49 Berlin
JP Japan JPN 392 +81 Tokyo
CA Canada CAN 124 +1 Ottawa

Configuration:

{
  "ExcelGenerations": [
    {
      "ModelType": "RecordStruct",
      "SourceFile": "/Sources/countries.xlsx",
      "SheetName": null,
      "Namespace": "MyApp.Data.Geography",
      "RootClassName": "Country",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "GenerateModelClass": true,
      "GenerateStaticTable": true,
      "StaticClassName": "Countries",
      "GenerateAllCollection": true,
      "ColumnMappings": {
        "Code": "IsoCode",
        "ISO3": "Iso3Code"
      },
      "PropertyTypeOverrides": {
        "NumericCode": "int",
        "PhonePrefix": "string"
      }
    }
  ]
}

Generated Code:

namespace MyApp.Data.Geography
{
    // Model class
    public record struct Country
    {
        public string IsoCode { get; init; }
        public string Name { get; init; }
        public string Iso3Code { get; init; }
        public int NumericCode { get; init; }
        public string PhonePrefix { get; init; }
        public string Capital { get; init; }
    }

    // Static lookup table
    public static class Countries
    {
        public static Country US => new Country
        {
            IsoCode = "US",
            Name = "United States",
            Iso3Code = "USA",
            NumericCode = 840,
            PhonePrefix = "+1",
            Capital = "Washington, D.C."
        };

        public static Country GB => new Country
        {
            IsoCode = "GB",
            Name = "United Kingdom",
            Iso3Code = "GBR",
            NumericCode = 826,
            PhonePrefix = "+44",
            Capital = "London"
        };

        public static Country DE => new Country
        {
            IsoCode = "DE",
            Name = "Germany",
            Iso3Code = "DEU",
            NumericCode = 276,
            PhonePrefix = "+49",
            Capital = "Berlin"
        };

        // ... more countries

        public static IReadOnlyList<Country> All { get; } = new[]
        {
            US, GB, DE, JP, CA
        };

        public static Country GetByCode(string code)
        {
            return All.FirstOrDefault(c => c.IsoCode == code);
        }
    }
}

Usage:

using MyApp.Data.Geography;

// Access individual countries
var usa = Countries.US;
Console.WriteLine($"{usa.Name} - {usa.PhonePrefix}");

// Get all countries
var allCountries = Countries.All;
foreach (var country in allCountries)
{
    Console.WriteLine($"{country.Name} ({country.IsoCode})");
}

// Lookup by code
var germany = Countries.GetByCode("DE");

Example 2: Product Categories with Hierarchies

Excel File: product-categories.xlsx

CategoryId CategoryName ParentId SortOrder Active Description
1 Electronics   1 Y Electronic devices and accessories
2 Computers 1 1 Y Desktop and laptop computers
3 Laptops 2 1 Y Portable computers
4 Desktops 2 2 Y Desktop computers
5 Smartphones 1 2 Y Mobile phones

Configuration:

{
  "ExcelGenerations": [
    {
      "ModelType": "Class",
      "SourceFile": "/Sources/product-categories.xlsx",
      "Namespace": "MyApp.Catalog",
      "RootClassName": "ProductCategory",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "GenerateModelClass": true,
      "GenerateStaticTable": true,
      "StaticClassName": "ProductCategories",
      "GenerateAllCollection": true,
      "PropertyTypeOverrides": {
        "CategoryId": "int",
        "ParentId": "int?",
        "SortOrder": "int",
        "Active": "bool"
      },
      "ColumnMappings": {
        "Active": "IsActive"
      }
    }
  ]
}

Generated Classes:

namespace MyApp.Catalog
{
    public class ProductCategory
    {
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        public int? ParentId { get; set; }
        public int SortOrder { get; set; }
        public bool IsActive { get; set; }
        public string Description { get; set; }
    }

    public static class ProductCategories
    {
        public static ProductCategory Electronics => new ProductCategory
        {
            CategoryId = 1,
            CategoryName = "Electronics",
            ParentId = null,
            SortOrder = 1,
            IsActive = true,
            Description = "Electronic devices and accessories"
        };

        public static ProductCategory Computers => new ProductCategory
        {
            CategoryId = 2,
            CategoryName = "Computers",
            ParentId = 1,
            SortOrder = 1,
            IsActive = true,
            Description = "Desktop and laptop computers"
        };

        // ... more categories

        public static IReadOnlyList<ProductCategory> All { get; } = new[]
        {
            Electronics,
            Computers,
            Laptops,
            Desktops,
            Smartphones
        };

        public static ProductCategory GetById(int id)
        {
            return All.FirstOrDefault(c => c.CategoryId == id);
        }

        public static IEnumerable<ProductCategory> GetChildren(int parentId)
        {
            return All.Where(c => c.ParentId == parentId);
        }
    }
}

Usage:

using MyApp.Catalog;

// Get root categories
var rootCategories = ProductCategories.All
    .Where(c => c.ParentId == null);

// Get children of Electronics
var electronicsChildren = ProductCategories.GetChildren(1);

// Build category tree
var category = ProductCategories.Computers;
Console.WriteLine($"{category.CategoryName}: {category.Description}");

Excel Generation Configuration Options

Property Type Description
ModelType string Type of model to generate: Class, Struct, Record, RecordStruct
SourceFile string Path to the Excel file (relative to project root)
SheetName string? Specific sheet name. If null, uses first sheet
Namespace string Namespace for generated classes
RootClassName string Name of the model class
KeyColumn string Column letter to use as key (e.g., “A”, “B”)
HeaderRowIndex int Row number containing column headers (1-based)
DataStartRowIndex int First row containing data (1-based)
GenerateModelClass bool Whether to generate the model class
GenerateStaticTable bool Whether to generate static lookup class
StaticClassName string Name of the static lookup class
GenerateAllCollection bool Whether to generate All property with all records
ColumnMappings object Dictionary mapping Excel column names to property names
PropertyTypeOverrides object Dictionary specifying custom types for properties
OutputPath string? Custom output path for generated files

Tips for Excel Generation

  1. Column Headers: Use clear, descriptive names in the header row. These become property names.

  2. Data Types: By default, all columns are strings. Use PropertyTypeOverrides to specify correct types:
    "PropertyTypeOverrides": {
      "Id": "int",
      "Price": "decimal",
      "IsActive": "bool",
      "CreatedDate": "DateTime"
    }
    
  3. Naming: Use ColumnMappings to rename columns that don’t follow C# naming conventions:
    "ColumnMappings": {
      "Full Name": "FullName",
      "E-Mail": "Email",
      "ZIP Code": "PostalCode"
    }
    
  4. Model Types:
    • RecordStruct: Immutable, value type, best for small lookup data
    • Record: Immutable, reference type, good for DTOs
    • Class: Mutable, reference type, most flexible
    • Struct: Mutable, value type, for small data structures
  5. Key Column: Choose a unique identifier column (usually first column) for generating property accessors.

AutoGenerateDto Attribute Reference

The AutoGenerateDto attribute is applied to classes or enums to generate DTOs at compile-time.

Basic Usage

[AutoGenerateDto]
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}
// Generates: UserDto class with mapping methods

Attribute Properties

Namespace and Naming

Property Type Default Description
Namespace string null Target namespace for generated DTO. If null, uses source class namespace
Prefix string ”” Prefix for generated class name (e.g., “Com” → “ComUserDto”)
Suffix string “Dto” Suffix for generated class name (e.g., “Dto” → “UserDto”)
GeneratedClassName string null Override complete class name. Ignores prefix/suffix if set

Example:

[AutoGenerateDto(
    Namespace = "MyApp.Api.Dtos",
    Prefix = "Api",
    Suffix = "Response"
)]
public class User { }
// Generates: MyApp.Api.Dtos.ApiUserResponse

Mapping Configuration

Property Type Default Description
GenerateMapping bool true Generate extension methods for mapping (ToDto/ToSource)
ToDtoMethodName string null Name of the method to convert source to DTO (e.g., “ToDto”)
ToSourceMethodName string null Name of the method to convert DTO back to source (e.g., “ToEntity”)

Example:

[AutoGenerateDto(
    ToDtoMethodName = "ToApiModel",
    ToSourceMethodName = "ToEntity"
)]
public class User { }

// Usage:
var dto = user.ToApiModel();
var entity = dto.ToEntity();

Property Control

Property Type Default Description
PropertiesToIgnore string[] null Property names to exclude from DTO generation

Example:

[AutoGenerateDto(PropertiesToIgnore = new[] { "Password", "InternalId" })]
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Password { get; set; }  // Not included in DTO
    public Guid InternalId { get; set; }  // Not included in DTO
}

Alternative: Use [IgnoreOnGeneration] attribute on properties:

public class User
{
    public int Id { get; set; }
    
    [IgnoreOnGeneration]
    public string Password { get; set; }  // Not included in DTO
}

Inheritance and Interfaces

Property Type Default Description
BaseType string null Base type for generated DTO (e.g., “BaseDto”)
Interfaces string[] null Interfaces to implement (e.g., “IDto”, “IValidatable”)
AutoGenerateDerived bool false Automatically generate DTOs for derived classes

Example:

[AutoGenerateDto(
    BaseType = "EntityBase",
    Interfaces = new[] { "IDto", "IAuditable" }
)]
public class User { }

// Generates:
public class UserDto : EntityBase, IDto, IAuditable
{
    // Properties...
}

COM Compatibility

Property Type Default Description
IsComCompatible bool false Generate COM-visible and COM-compatible code with GUIDs

Example:

[AutoGenerateDto(IsComCompatible = true)]
public class User { }

// Generates:
[ComVisible(true)]
[Guid("...")]
public class UserDto
{
    // Properties...
}

Modifiers and Access

Property Type Default Description
ClassModifier Modifier Public Access modifier for generated class (Public, Internal, Private)
InterfaceModifier Modifier Public Access modifier for generated interface
DefaultPropertyInterfaceAccess InterfaceProperty GetSet Default property access in interface (Get, Set, GetSet)

Example:

[AutoGenerateDto(
    ClassModifier = Modifier.Internal,
    InterfaceModifier = Modifier.Public
)]
public class User { }

Attributes and Metadata

Property Type Default Description
KeepAttributesOnGeneratedClass bool false Copy attributes from source class to DTO
KeepAttributesOnGeneratedInterface bool false Copy attributes from source class to generated interface
KeepPropertyAttributesOnGeneratedClass bool false Copy property attributes to DTO properties
KeepPropertyAttributesOnGeneratedInterface bool false Copy property attributes to interface properties
PreClassString string null String to add before class (e.g., attributes)
PreInterfaceString string null String to add before interface (e.g., attributes)

Example:

[AutoGenerateDto(
    PreClassString = "[Serializable]\n[JsonObject]",
    KeepPropertyAttributesOnGeneratedClass = true
)]
public class User
{
    [Required]
    [StringLength(100)]
    public string Name { get; set; }
}

// Generates:
[Serializable]
[JsonObject]
public class UserDto
{
    [Required]
    [StringLength(100)]
    public string Name { get; set; }
}

Namespaces and Using Directives

Property Type Default Description
Usings string[] null Additional using directives
AddReferencedNamespacesUsings bool false Add usings for all referenced namespaces
AddContainingNamespaceUsings bool false Add using for source class namespace

Example:

[AutoGenerateDto(
    Usings = new[] { "System.ComponentModel.DataAnnotations", "MyApp.Helpers" },
    AddReferencedNamespacesUsings = true
)]
public class User { }

Complete Example

using Nextended.Core.Attributes;
using Nextended.Core.Enums;

[AutoGenerateDto(
    // Naming
    Namespace = "MyApp.Api.Dtos",
    Suffix = "Response",
    
    // Mapping
    ToDtoMethodName = "ToApiResponse",
    ToSourceMethodName = "ToEntity",
    
    // Inheritance
    BaseType = "BaseResponse",
    Interfaces = new[] { "IApiResponse" },
    
    // Properties
    PropertiesToIgnore = new[] { "PasswordHash", "InternalData" },
    
    // Modifiers
    ClassModifier = Modifier.Public,
    
    // Attributes
    KeepPropertyAttributesOnGeneratedClass = true,
    PreClassString = "[Serializable]",
    
    // Namespaces
    Usings = new[] { "System.ComponentModel.DataAnnotations" }
)]
public class User
{
    public int Id { get; set; }
    
    [Required]
    [StringLength(100)]
    public string Username { get; set; }
    
    [EmailAddress]
    public string Email { get; set; }
    
    [IgnoreOnGeneration]
    public string PasswordHash { get; set; }
    
    public DateTime CreatedAt { get; set; }
}

// Usage:
var user = GetUser();
var response = user.ToApiResponse();
var userAgain = response.ToEntity();

Configuration Options

DtoGeneration Options (CodeGen.config.json)

These settings apply to all DTOs unless overridden by attribute properties.

Option Type Description
Namespace string Default namespace for generated DTOs
Suffix string Default suffix for DTO class names (default: “Dto”)
Prefix string Default prefix for DTO class names
ToDtoMethodName string Default name of ToDto extension method
ToSourceMethodName string Default name of ToSource extension method
IsComCompatible bool Generate COM-compatible GUIDs by default
GeneratePartial bool Generate as partial classes (default: true)
OneFilePerClass bool Create separate file per DTO (default: true)
CreateRegions bool Add region blocks (default: true)
CreateComments bool Add XML comments (default: true)
ComIdClassName string Name of the class for COM GUIDs
ComIdClassPropertyFormat string Format for COM ID properties
ComIdClassModifier string Modifier for COM ID class
BaseType string Default base type for DTOs
Interfaces string[] Default interfaces for DTOs
Usings string[] Default using directives
KeepAttributesOnGeneratedClass bool Copy attributes from source classes
KeepAttributesOnGeneratedInterface bool Copy attributes to interfaces
AddReferencedNamespacesUsings bool Add usings for referenced namespaces
AddContainingNamespaceUsings bool Add using for source namespaces
PreInterfaceString string String before generated interfaces
PreClassString string String before generated classes
DefaultMappingSettings object Default mapping settings configuration
OutputPath string Output directory for generated files

StructureGeneration Options (JSON/XML)

Complete reference for generating classes from JSON and XML files.

Option Type Required Description
SourceFile string Yes Path to JSON or XML source file (relative to project root)
RootClassName string Yes Name of the root generated class
Namespace string Yes Target namespace for generated classes
Prefix string No Prefix for all generated class names
Suffix string No Suffix for all generated class names
Ignore string[] No Property paths to ignore (e.g., “Database.Password”)
OutputPath string No Output directory for generated files (if null, added to compilation)

JSON Generation Examples

Basic Configuration File:

appsettings.json:

{
  "Database": {
    "ConnectionString": "Server=localhost;Database=MyDb;",
    "MaxPoolSize": 100,
    "EnableLogging": true
  },
  "Api": {
    "BaseUrl": "https://api.example.com",
    "Timeout": 30,
    "ApiKey": "secret-key"
  }
}

Configuration:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Config/appsettings.json",
      "RootClassName": "AppSettings",
      "Namespace": "MyApp.Configuration"
    }
  ]
}

Generated Code:

namespace MyApp.Configuration
{
    public class AppSettings
    {
        public Database Database { get; set; }
        public Api Api { get; set; }
    }

    public class Database
    {
        public string ConnectionString { get; set; }
        public int MaxPoolSize { get; set; }
        public bool EnableLogging { get; set; }
    }

    public class Api
    {
        public string BaseUrl { get; set; }
        public int Timeout { get; set; }
        public string ApiKey { get; set; }
    }
}

Usage:

var config = new AppSettings
{
    Database = new Database
    {
        ConnectionString = "...",
        MaxPoolSize = 100
    }
};

Advanced with Ignore:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Config/appsettings.json",
      "RootClassName": "AppSettings",
      "Namespace": "MyApp.Configuration",
      "Prefix": "Cfg",
      "Ignore": ["Api.ApiKey", "Database.ConnectionString"],
      "OutputPath": "./Generated/Config/"
    }
  ]
}

Complex JSON Structure:

users.json:

{
  "users": [
    {
      "id": 1,
      "name": "John Doe",
      "email": "john@example.com",
      "roles": ["admin", "user"],
      "metadata": {
        "lastLogin": "2024-01-15T10:30:00Z",
        "loginCount": 42
      }
    }
  ],
  "pagination": {
    "page": 1,
    "pageSize": 10,
    "total": 100
  }
}

Generated Classes:

public class UsersRoot
{
    public List<User> Users { get; set; }
    public Pagination Pagination { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
    public List<string> Roles { get; set; }
    public Metadata Metadata { get; set; }
}

public class Metadata
{
    public DateTime LastLogin { get; set; }
    public int LoginCount { get; set; }
}

public class Pagination
{
    public int Page { get; set; }
    public int PageSize { get; set; }
    public int Total { get; set; }
}

XML Generation Examples

Simple XML Configuration:

<!-- config.xml -->
<Configuration>
  <Server>
    <Host>localhost</Host>
    <Port>8080</Port>
    <UseSSL>true</UseSSL>
  </Server>
  <Logging>
    <Level>Information</Level>
    <FilePath>logs/app.log</FilePath>
  </Logging>
</Configuration>

Configuration:

{
  "StructureGenerations": [
    {
      "SourceFile": "/Config/config.xml",
      "RootClassName": "Configuration",
      "Namespace": "MyApp.Config"
    }
  ]
}

Generated Code:

namespace MyApp.Config
{
    public class Configuration
    {
        public Server Server { get; set; }
        public Logging Logging { get; set; }
    }

    public class Server
    {
        public string Host { get; set; }
        public int Port { get; set; }
        public bool UseSSL { get; set; }
    }

    public class Logging
    {
        public string Level { get; set; }
        public string FilePath { get; set; }
    }
}

ExcelGeneration Options

Complete reference for generating classes from Excel spreadsheets.

Option Type Required Description
SourceFile string Yes Path to Excel file (.xlsx, .xls)
SheetName string No Specific sheet name (null for first sheet)
Namespace string Yes Target namespace for generated classes
RootClassName string Yes Name of the model/record class
StaticClassName string No Name of the static lookup class
KeyColumn string No Column letter to use as key (e.g., “A”, “B”)
HeaderRowIndex int Yes Row number containing column headers (1-based)
DataStartRowIndex int Yes First row number containing data (1-based)
ModelType string No Type of model: “Class”, “RecordClass”, “RecordStruct” (default: “Class”)
GenerateModelClass bool No Generate the model/record class (default: true)
GenerateStaticTable bool No Generate static lookup class with data (default: false)
GenerateAllCollection bool No Generate collection of all records (default: false)
ColumnMappings Dictionary<string,string> No Map Excel column names to property names
PropertyTypeOverrides Dictionary<string,string> No Override property types
OutputPath string No Output directory for generated files

Excel Generation Examples

Example 1: Simple Data Table

Excel File (countries.xlsx):

| Code | Name           | Population | Capital    |
|------|----------------|------------|------------|
| US   | United States  | 331000000  | Washington |
| UK   | United Kingdom | 67000000   | London     |
| FR   | France         | 65000000   | Paris      |

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Data/countries.xlsx",
      "Namespace": "MyApp.Data",
      "RootClassName": "Country",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "GenerateModelClass": true
    }
  ]
}

Generated Code:

namespace MyApp.Data
{
    public class Country
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public int Population { get; set; }
        public string Capital { get; set; }
    }
}

Example 2: Static Lookup Table

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Data/countries.xlsx",
      "Namespace": "MyApp.Data",
      "RootClassName": "Country",
      "StaticClassName": "Countries",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "GenerateModelClass": true,
      "GenerateStaticTable": true,
      "GenerateAllCollection": true
    }
  ]
}

Generated Code:

namespace MyApp.Data
{
    public class Country
    {
        public string Code { get; set; }
        public string Name { get; set; }
        public int Population { get; set; }
        public string Capital { get; set; }
    }

    public static class Countries
    {
        public static Country US { get; } = new Country
        {
            Code = "US",
            Name = "United States",
            Population = 331000000,
            Capital = "Washington"
        };

        public static Country UK { get; } = new Country
        {
            Code = "UK",
            Name = "United Kingdom",
            Population = 67000000,
            Capital = "London"
        };

        public static Country FR { get; } = new Country
        {
            Code = "FR",
            Name = "France",
            Population = 65000000,
            Capital = "Paris"
        };

        public static IReadOnlyList<Country> All { get; } = new[]
        {
            US, UK, FR
        };
    }
}

Usage:

// Access by key
var us = Countries.US;
Console.WriteLine($"{us.Name}: {us.Population}");

// Access all
foreach (var country in Countries.All)
{
    Console.WriteLine(country.Name);
}

// Find by code
var france = Countries.All.FirstOrDefault(c => c.Code == "FR");

Example 3: Record Struct with Column Mapping

Excel File (products.xlsx):

| Product ID | Product Name    | Unit Price | In Stock |
|------------|-----------------|------------|----------|
| P001       | Widget A        | 19.99      | Yes      |
| P002       | Gadget B        | 29.99      | No       |

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Data/products.xlsx",
      "Namespace": "MyApp.Catalog",
      "RootClassName": "Product",
      "ModelType": "RecordStruct",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "ColumnMappings": {
        "Product ID": "ProductId",
        "Product Name": "Name",
        "Unit Price": "Price",
        "In Stock": "Available"
      }
    }
  ]
}

Generated Code:

namespace MyApp.Catalog
{
    public record struct Product
    {
        public string ProductId { get; init; }
        public string Name { get; init; }
        public double Price { get; init; }
        public string Available { get; init; }
    }
}

Example 4: Custom Property Types

Excel File (locations.xlsx):

| Code | Name        | Coordinates      | Status  | Type      |
|------|-------------|------------------|---------|-----------|
| NYC  | New York    | 40.7128,-74.0060 | Active  | Primary   |
| LAX  | Los Angeles | 34.0522,-118.2437| Active  | Secondary |

Custom Types:

namespace MyApp.Types
{
    public record struct Coordinates
    {
        public double Latitude { get; init; }
        public double Longitude { get; init; }

        public static Coordinates Parse(string value)
        {
            var parts = value.Split(',');
            return new Coordinates
            {
                Latitude = double.Parse(parts[0]),
                Longitude = double.Parse(parts[1])
            };
        }
    }

    public enum LocationStatus { Active, Inactive }
    public enum LocationType { Primary, Secondary, Tertiary }
}

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Data/locations.xlsx",
      "Namespace": "MyApp.Data",
      "RootClassName": "Location",
      "StaticClassName": "Locations",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "ModelType": "RecordStruct",
      "GenerateStaticTable": true,
      "PropertyTypeOverrides": {
        "Coordinates": "MyApp.Types.Coordinates",
        "Status": "MyApp.Types.LocationStatus",
        "Type": "MyApp.Types.LocationType"
      },
      "ColumnMappings": {
        "Status": "Status",
        "Type": "Type"
      }
    }
  ]
}

Generated Code:

namespace MyApp.Data
{
    public record struct Location
    {
        public string Code { get; init; }
        public string Name { get; init; }
        public MyApp.Types.Coordinates Coordinates { get; init; }
        public MyApp.Types.LocationStatus Status { get; init; }
        public MyApp.Types.LocationType Type { get; init; }
    }

    public static class Locations
    {
        public static Location NYC { get; } = new Location
        {
            Code = "NYC",
            Name = "New York",
            Coordinates = MyApp.Types.Coordinates.Parse("40.7128,-74.0060"),
            Status = MyApp.Types.LocationStatus.Active,
            Type = MyApp.Types.LocationType.Primary
        };

        public static Location LAX { get; } = new Location
        {
            Code = "LAX",
            Name = "Los Angeles",
            Coordinates = MyApp.Types.Coordinates.Parse("34.0522,-118.2437"),
            Status = MyApp.Types.LocationStatus.Active,
            Type = MyApp.Types.LocationType.Secondary
        };
    }
}

Example 5: Multiple Sheets

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Data/masterdata.xlsx",
      "SheetName": "Customers",
      "Namespace": "MyApp.Data",
      "RootClassName": "Customer",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2
    },
    {
      "SourceFile": "/Data/masterdata.xlsx",
      "SheetName": "Products",
      "Namespace": "MyApp.Data",
      "RootClassName": "Product",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2
    }
  ]
}

Example 6: Complete Real-World Scenario

Excel File (scac_codes.xlsx) - Shipping Carrier Codes:

| SCAC | Carrier Name          | Country | Contact Email      | Active |
|------|-----------------------|---------|--------------------|--------|
| ABCD | ABC Logistics         | USA     | info@abclog.com    | Yes    |
| EFGH | EFG Shipping Co       | USA     | contact@efg.com    | Yes    |
| WXYZ | WXY International     | CAN     | support@wxy.com    | No     |

Configuration:

{
  "ExcelGenerations": [
    {
      "SourceFile": "/Sources/scac_codes.xlsx",
      "SheetName": null,
      "Namespace": "Shipping.Data",
      "RootClassName": "ScacCode",
      "StaticClassName": "ScacCodes",
      "KeyColumn": "A",
      "HeaderRowIndex": 1,
      "DataStartRowIndex": 2,
      "ModelType": "RecordStruct",
      "GenerateModelClass": true,
      "GenerateStaticTable": true,
      "GenerateAllCollection": true,
      "ColumnMappings": {
        "SCAC": "Code",
        "Carrier Name": "CarrierName",
        "Contact Email": "Email"
      },
      "PropertyTypeOverrides": {
        "Active": "bool"
      },
      "OutputPath": "./Generated/Shipping/"
    }
  ]
}

Generated Usage:

using Shipping.Data;

// Lookup by key
var carrier = ScacCodes.ABCD;
Console.WriteLine($"Carrier: {carrier.CarrierName}");

// Search all
var activeCarriers = ScacCodes.All
    .Where(c => c.Active)
    .ToList();

// Use in dropdown
var dropdownItems = ScacCodes.All
    .Select(c => new { Value = c.Code, Label = c.CarrierName })
    .ToList();

Best Practices for Excel Generation

  1. Clean Headers: Use clear, descriptive column headers without special characters
  2. Consistent Data Types: Ensure columns contain consistent data types
  3. Key Columns: Use columns with unique values for KeyColumn
  4. Type Overrides: Use PropertyTypeOverrides for enums, custom types, or specific numeric types
  5. Column Mapping: Use ColumnMappings to create clean property names from complex headers
  6. Model Types:
    • Use RecordStruct for small, immutable data
    • Use RecordClass for immutable reference types
    • Use Class for mutable data that needs modification
  7. Output Path: Use OutputPath to organize generated files separately from source code

Best Practices

1. Use Meaningful Names

[AutoGenerateDto(
    Namespace = "MyApp.Api.Dtos",
    ToDtoMethodName = "ToApiDto",
    ToSourceMethodName = "ToEntity"
)]
public class User { }

2. Organize Generated Code

{
  "DtoGeneration": {
    "Namespace": "MyApp.Generated.Dtos",
    "OutputPath": "./Generated/Dtos/",
    "OneFilePerClass": true
  }
}

3. Version Control Generated Files

Add to .gitignore if you regenerate on build, or commit them if you want to review changes.

4. Use Partial Classes for Customization

Generated as partial classes allow you to extend:

// Generated
public partial class UserDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// Your custom code
public partial class UserDto
{
    public string DisplayName => $"User: {Name}";
}

Attribute Reference

AutoGenerateDtoAttribute

The AutoGenerateDtoAttribute is the primary attribute for generating DTOs from your classes. It provides extensive configuration options to control the generated code.

Properties

Namespace Configuration
[AutoGenerateDto(Namespace = "MyApp.Dtos")]
public class User { }

Namespace (string?)
Sets the namespace for the generated DTO. If not specified, uses the configuration file default or the source class namespace with a “Dto” suffix.

Naming Configuration
[AutoGenerateDto(
    Prefix = "Api",
    Suffix = "Response",
    GeneratedClassName = "CustomUserName"  // Overrides prefix/suffix
)]
public class User { }
// Generates: ApiUserResponse or CustomUserName

Prefix (string?)
Adds a prefix to the generated class name. Default: empty string.

Suffix (string?)
Adds a suffix to the generated class name. Default: “Dto”.

GeneratedClassName (string?)
Explicitly sets the generated class name, overriding prefix and suffix logic.

Property Filtering
public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    [IgnoreOnGeneration]
    public string Password { get; set; }  // Excluded from DTO
}

// Alternative: Configure in attribute
[AutoGenerateDto(PropertiesToIgnore = new[] { "Password", "InternalId" })]
public class User 
{
    public string Password { get; set; }
    public string InternalId { get; set; }
}

PropertiesToIgnore (string[])
Array of property names to exclude from the generated DTO.

Mapping Configuration
[AutoGenerateDto(
    GenerateMapping = true,
    ToDtoMethodName = "ToUserDto",
    ToSourceMethodName = "ToUser"
)]
public class User { }

// Usage
var user = GetUser();
var dto = user.ToUserDto();
var userAgain = dto.ToUser();

GenerateMapping (bool)
When true, generates extension methods for mapping between source and DTO. Default: true.

ToDtoMethodName (string?)
Name of the method that converts source to DTO. Default: “ToDto”.

ToSourceMethodName (string?)
Name of the method that converts DTO back to source. Default: “ToSource”.

COM Compatibility
[AutoGenerateDto(IsComCompatible = true)]
public class User { }

IsComCompatible (bool)
Generates COM-visible classes with appropriate attributes and GUIDs. Used for COM interop scenarios.

Type Configuration
[AutoGenerateDto(
    BaseType = "EntityBase",
    Interfaces = new[] { "IEntity", "IAuditable" }
)]
public class User { }

// Generates:
public class UserDto : EntityBase, IEntity, IAuditable { }

BaseType (string?)
Sets the base class for the generated DTO.

Interfaces (string[]?)
Adds interfaces that the generated DTO should implement.

Modifiers
[AutoGenerateDto(
    ClassModifier = Modifier.Internal,
    InterfaceModifier = Modifier.Public
)]
public class User { }

ClassModifier (Modifier)
Access modifier for the generated class. Options: Unset, Public, Private, Protected, Internal.

InterfaceModifier (Modifier)
Access modifier for the generated interface (if applicable).

DefaultPropertyInterfaceAccess (InterfaceProperty)
Default accessor type for interface properties. Options: Unset, GetAndSet, Get, Set.

Using Directives
[AutoGenerateDto(
    Usings = new[] { "System.Text.Json.Serialization", "MyApp.CustomTypes" },
    AddReferencedNamespacesUsings = true,
    AddContainingNamespaceUsings = true
)]
public class User { }

Usings (string[]?)
Additional using directives to include in the generated file.

AddReferencedNamespacesUsings (bool)
Automatically includes using directives for all referenced types.

AddContainingNamespaceUsings (bool)
Includes using directive for the source class’s namespace.

Custom Code Injection
[AutoGenerateDto(
    PreInterfaceString = "[JsonObject]",
    PreClassString = "[Serializable]\n[DataContract]"
)]
public class User { }

// Generates:
[JsonObject]
public interface IUserDto { }

[Serializable]
[DataContract]
public class UserDto { }

PreInterfaceString (string?)
Code to insert before the generated interface declaration (e.g., attributes).

PreClassString (string?)
Code to insert before the generated class declaration (e.g., attributes).

Attribute Preservation
[AutoGenerateDto(
    KeepAttributesOnGeneratedClass = true,
    KeepAttributesOnGeneratedInterface = true,
    KeepPropertyAttributesOnGeneratedClass = true,
    KeepPropertyAttributesOnGeneratedInterface = true
)]
[DataContract]
public class User 
{
    [Required]
    [DataMember]
    public string Name { get; set; }
}

// Generated DTO keeps the attributes
[DataContract]
public class UserDto 
{
    [Required]
    [DataMember]
    public string Name { get; set; }
}

KeepAttributesOnGeneratedClass (bool)
Copies class-level attributes from source to generated class.

KeepAttributesOnGeneratedInterface (bool)
Copies class-level attributes from source to generated interface.

KeepPropertyAttributesOnGeneratedClass (bool)
Copies property-level attributes from source properties to generated class properties.

KeepPropertyAttributesOnGeneratedInterface (bool)
Copies property-level attributes from source properties to generated interface properties.

Derived Type Generation
[AutoGenerateDto(AutoGenerateDerived = true)]
public class BaseEntity { }

public class User : BaseEntity { }  // DTO automatically generated
public class Product : BaseEntity { }  // DTO automatically generated

AutoGenerateDerived (bool)
Automatically generates DTOs for all derived types when applied to a base class.

IgnoreOnGenerationAttribute

Use this attribute to exclude specific properties or fields from DTO generation.

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    [IgnoreOnGeneration]
    public string Password { get; set; }
    
    [IgnoreOnGeneration]
    public byte[] PasswordHash { get; set; }
}

GenerationPropertySettingAttribute

Fine-tune individual property generation with this attribute.

public class User
{
    public int Id { get; set; }
    
    [GenerationPropertySetting(
        PropertyName = "FullName",  // Rename in DTO
        MapWithClassMapper = true,   // Use ClassMapper for conversion
        InterfaceAccess = InterfaceProperty.Get,  // Read-only in interface
        PreClassString = "[JsonProperty(\"full_name\")]",
        KeepAttributesOnGeneratedClass = true
    )]
    public string Name { get; set; }
}

// Generated:
public interface IUserDto
{
    string FullName { get; }  // Read-only
}

public class UserDto : IUserDto
{
    [JsonProperty("full_name")]
    public string FullName { get; set; }
}

Properties:

  • PropertyName (string?) - Custom name for the property in the generated DTO
  • MapWithClassMapper (bool) - Use ClassMapper for type conversion during mapping
  • InterfaceAccess (InterfaceProperty) - Property accessor type in interfaces (Get, Set, or GetAndSet)
  • PreInterfaceString (string?) - Code to insert before the property in the interface
  • PreClassString (string?) - Code to insert before the property in the class
  • KeepAttributesOnGeneratedClass (bool) - Keep property attributes in generated class
  • KeepAttributesOnGeneratedInterface (bool) - Keep property attributes in generated interface

Complete Example: Advanced DTO Generation

using Nextended.Core.Attributes;
using Nextended.Core.Enums;

namespace MyApp.Domain
{
    /// <summary>
    /// User entity with complete DTO generation configuration
    /// </summary>
    [AutoGenerateDto(
        Namespace = "MyApp.Dtos",
        Suffix = "Response",
        ToDtoMethodName = "ToUserResponse",
        ToSourceMethodName = "ToUserEntity",
        GenerateMapping = true,
        BaseType = "AuditableDto",
        Interfaces = new[] { "IUserResponse", "IIdentifiable" },
        Usings = new[] { "System.Text.Json.Serialization" },
        ClassModifier = Modifier.Public,
        PreClassString = "[JsonSerializable(typeof(UserResponse))]",
        KeepPropertyAttributesOnGeneratedClass = true,
        PropertiesToIgnore = new[] { "PasswordHash", "PasswordSalt" }
    )]
    public class User
    {
        public int Id { get; set; }
        
        [Required]
        [MaxLength(100)]
        public string UserName { get; set; }
        
        [Required]
        [EmailAddress]
        public string Email { get; set; }
        
        [GenerationPropertySetting(
            PropertyName = "FullName",
            PreClassString = "[JsonPropertyName(\"fullName\")]"
        )]
        public string Name { get; set; }
        
        [IgnoreOnGeneration]
        public byte[] PasswordHash { get; set; }
        
        [IgnoreOnGeneration]
        public byte[] PasswordSalt { get; set; }
        
        public DateTime CreatedAt { get; set; }
        public DateTime? ModifiedAt { get; set; }
        
        public List<Address> Addresses { get; set; }
    }
    
    [AutoGenerateDto(
        Namespace = "MyApp.Dtos",
        Suffix = "Response"
    )]
    public class Address
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
    }
}

Generated result:

namespace MyApp.Dtos
{
    using System;
    using System.Collections.Generic;
    using System.Text.Json.Serialization;
    using System.ComponentModel.DataAnnotations;
    
    [JsonSerializable(typeof(UserResponse))]
    public class UserResponse : AuditableDto, IUserResponse, IIdentifiable
    {
        [Required]
        [MaxLength(100)]
        public string UserName { get; set; }
        
        [Required]
        [EmailAddress]
        public string Email { get; set; }
        
        [JsonPropertyName("fullName")]
        public string FullName { get; set; }
        
        public DateTime CreatedAt { get; set; }
        public DateTime? ModifiedAt { get; set; }
        
        public List<AddressResponse> Addresses { get; set; }
    }
    
    public class AddressResponse
    {
        public string Street { get; set; }
        public string City { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
    }
}

Usage:

var user = await _userRepository.GetByIdAsync(userId);
var response = user.ToUserResponse();
return Ok(response);

Troubleshooting

Generated Code Not Appearing

  1. Ensure CodeGen.config.json is marked as AdditionalFiles
  2. Clean and rebuild: dotnet clean && dotnet build
  3. Check build output for generator messages
  4. Verify source generators are enabled in IDE

Build Errors After Generation

  1. Check namespace conflicts
  2. Verify property types are valid
  3. Ensure all dependencies are installed

Supported Frameworks

  • .NET Standard 2.0 (Generator)
  • .NET 8.0+ (Generated code)

Dependencies

  • Roslyn APIs for source generation
  • Nextended.Core for attributes

Sample Project

See the CodeGenSample project for complete examples.