Structura 1.0.0

dotnet add package Structura --version 1.0.0
                    
NuGet\Install-Package Structura -Version 1.0.0
                    
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="Structura" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Structura" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Structura" />
                    
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 Structura --version 1.0.0
                    
#r "nuget: Structura, 1.0.0"
                    
#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 Structura@1.0.0
                    
#: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=Structura&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Structura&version=1.0.0
                    
Install as a Cake Tool

Structura

<img src="./logo.png" width="256" height="256">

Fluent API-based Source Generator Type Manipulation Library

Structura is a flexible type generation library that converts anonymous types and EF Core projection results to strongly-typed types, with the ability to add, exclude, and change properties.

๐Ÿš€ Key Features

  • ๐ŸŽญ Anonymous Type Combination: Combine multiple anonymous types to create new types
  • ๐Ÿ”— EF Core Projection Support: Automatically convert EF Core Select results to strongly-typed types
  • โž• Property Addition: Add new properties to existing types (.Add())
  • โž– Property Exclusion: Exclude sensitive or unnecessary properties (.Exclude())
  • ๐Ÿ”„ Type Conversion: Change existing property types to different types (.ChangeType())
  • ๐ŸŽฏ Smart Converter: Automatically generate extension methods for converting anonymous objects to strong types
  • ๐Ÿท๏ธ Multiple Type Generation: Support for Records, Classes, and Structs
  • ๐Ÿงช Comprehensive Testing: Stability verified with 100+ unit tests

๐Ÿ“ฆ Installation

dotnet add package Structura

๐Ÿ—๏ธ Core Features

1. Anonymous Type Combination

Combine multiple anonymous types to create new strongly-typed types.

// Single anonymous type usage
var userInfo = new { Name = "John Doe", Age = 30, Department = "Development" };

TypeCombiner.Combine()
    .With(userInfo)
    .WithName("Employee")
    .AsRecord()
    .Generate();

// Usage: new Generated.Employee("Jane Smith", 25, "Design")

// Multiple anonymous type combination
var personal = new { FirstName = "John", LastName = "Doe" };
var work = new { Company = "TechCorp", Position = "Developer" };

TypeCombiner.Combine()
    .With(personal)
    .With(work)
    .WithName("FullProfile")
    .AsClass()
    .Generate();

2. EF Core Projection Support

Automatically convert EF Core Select results to strongly-typed types.

// EF Core projection query
var userProjection = dbContext.Users
    .Select(u => new { u.Name, u.Email, u.Department })
    .ToList();

// Strong type generation
TypeCombiner.Combine()
    .WithProjection(userProjection)
    .WithName("UserDto")
    .WithConverter()  // ๐Ÿ”ฅ Enable smart conversion
    .AsRecord()
    .Generate();

// Automatic conversion usage
List<Generated.UserDto> typedUsers = UserDto.FromCollection(userProjection);
Generated.UserDto singleUser = UserDto.FromSingle(userProjection.First());

3. ๐ŸŽฏ Smart Converter (Core Feature!)

The game-changer for EF Core projections! Generates static methods for automatically converting anonymous objects to strongly-typed types.

// Step 1: Generate type with converter enabled
var customerData = dbContext.Orders
    .GroupBy(o => o.CustomerId)
    .Select(g => new {
        CustomerId = g.Key,
        CustomerName = g.First().Customer.Name,
        TotalOrders = g.Count(),
        TotalSpent = g.Sum(o => o.Amount)
    })
    .ToList();

TypeCombiner.Combine()
    .WithProjection(customerData)
    .WithName("CustomerAnalytics")
    .WithConverter()  // ๐Ÿ”ฅ The magic begins!
    .AsRecord()
    .Generate();

// Step 2: Use conversion methods directly on the generated type
List<Generated.CustomerAnalytics> analytics = CustomerAnalytics.FromCollection(customerData);
Generated.CustomerAnalytics single = CustomerAnalytics.FromSingle(customerData.First());

// Strongly-typed anonymous objects are also convertible
var anonymousData = new[] {
    new { CustomerId = 1, CustomerName = "John Doe", TotalOrders = 5, TotalSpent = 150000m },
    new { CustomerId = 2, CustomerName = "Jane Smith", TotalOrders = 3, TotalSpent = 75000m }
};
List<Generated.CustomerAnalytics> converted = CustomerAnalytics.FromTypedCollection(anonymousData);

4. Property Manipulation Features

Property Addition
// Add new properties to existing types
var userData = new { Name = "John Doe", Email = "john@test.com" };

TypeCombiner.Combine()
    .With(userData)
    .Add("Id", typeof(int))
    .Add("CreatedAt", typeof(DateTime))
    .Add("Metadata", typeof(Dictionary<string, object>))
    .WithName("EnhancedUser")
    .AsClass()
    .Generate();

// Pure Add usage for type creation
TypeCombiner.Combine()
    .Add("Name", typeof(string))
    .Add("Value", typeof(int))
    .Add("IsActive", typeof(bool))
    .WithName("CustomType")
    .AsRecord()
    .Generate();
Property Exclusion
// Exclude sensitive information
var sensitiveData = new { 
    Name = "John Doe", 
    Age = 30, 
    Password = "secret123", 
    Email = "john@test.com" 
};

TypeCombiner.Combine()
    .With(sensitiveData)
    .Exclude("Password")  // Exclude password
    .WithName("SafeUser")
    .AsClass()
    .Generate();

// Multiple property exclusion
TypeCombiner.Combine()
    .With(userData)
    .Exclude("Password")
    .Exclude("InternalId")
    .WithName("PublicData")
    .Generate();
Type Conversion
// Property type conversion
var numericData = new { 
    Id = 1, 
    Price = 100m, 
    Quantity = 5, 
    IsActive = true 
};

TypeCombiner.Combine()
    .With(numericData)
    .ChangeType("Price", typeof(string))    // decimal โ†’ string
    .ChangeType("Quantity", typeof(long))   // int โ†’ long
    .ChangeType("IsActive", typeof(int))    // bool โ†’ int
    .WithName("ConvertedProduct")
    .AsClass()
    .Generate();

5. Complex Operations

All features can be used together.

// EF Core projection + property addition + type conversion + converter
var orderProjection = dbContext.Orders
    .Select(o => new { 
        o.Id, 
        o.CustomerName, 
        o.Amount, 
        o.OrderDate 
    })
    .ToList();

TypeCombiner.Combine()
    .WithProjection(orderProjection)
    .Add("ProcessedAt", typeof(DateTime))           // Property addition
    .Add("Status", typeof(string))                  // Property addition
    .ChangeType("Amount", typeof(string))           // decimal โ†’ string
    .Exclude("InternalId")                          // Property exclusion (if exists)
    .WithConverter()                                // Enable smart converter
    .WithName("ProcessedOrder")
    .AsRecord()
    .Generate();

// Complete conversion support
List<Generated.ProcessedOrder> orders = ProcessedOrder.FromCollection(orderProjection);

๐Ÿท๏ธ Supported Type Generation

Type Method Description Converter Support
Record .AsRecord() Generate immutable record types โœ… Full Support
Class .AsClass() Generate mutable class types โœ… Full Support
Struct .AsStruct() Generate value type structs โœ… Full Support

๐ŸŽฏ Target Frameworks

  • .NET Standard 2.0 and above
  • .NET 9 recommended
  • C# 12.0 syntax support

๐Ÿš€ Real-World Usage Scenarios

EF Core Integration

// Complex dashboard data generation
var dashboardData = await dbContext.Orders
    .Include(o => o.Customer)
    .GroupBy(o => new { o.CustomerId, o.Customer.Name })
    .Select(g => new {
        CustomerId = g.Key.CustomerId,
        CustomerName = g.Key.Name,
        TotalOrders = g.Count(),
        TotalRevenue = g.Sum(o => o.Amount),
        AverageOrderValue = g.Average(o => o.Amount),
        LastOrderDate = g.Max(o => o.OrderDate)
    })
    .ToListAsync();

// Strongly-typed DTO generation and conversion
TypeCombiner.Combine()
    .WithProjection(dashboardData)
    .Add("GeneratedAt", typeof(DateTime))
    .Add("ReportType", typeof(string))
    .WithName("CustomerDashboard")
    .WithConverter()
    .AsRecord()
    .Generate();

// Immediately available strongly-typed collection
List<Generated.CustomerDashboard> dashboard = CustomerDashboard.FromCollection(dashboardData);

// Complete type safety in business logic
var topCustomers = dashboard
    .Where(c => c.TotalRevenue > 100000)
    .OrderByDescending(c => c.TotalRevenue)
    .Take(10)
    .ToList();

API DTO Generation

// Generate public API DTO from internal entity
var internalUser = new { 
    Id = 1, 
    Name = "John Doe", 
    Email = "john@company.com", 
    Password = "hashed_password", 
    InternalNotes = "Important internal info",
    Salary = 5000000m
};

TypeCombiner.Combine()
    .With(internalUser)
    .Exclude("Password")       // Exclude password
    .Exclude("InternalNotes")  // Exclude internal info
    .Exclude("Salary")         // Exclude salary info
    .Add("PublicId", typeof(Guid))
    .WithConverter()
    .WithName("UserApiDto")
    .AsRecord()
    .Generate();

Data Transformation Pipeline

// Convert external API response to internal format
var externalApiResponse = new[] {
    new { user_id = "123", full_name = "John Doe", email_addr = "john@example.com", is_active = "1" },
    new { user_id = "456", full_name = "Jane Smith", email_addr = "jane@example.com", is_active = "0" }
};

TypeCombiner.Combine()
    .WithProjection(externalApiResponse)
    .ChangeType("user_id", typeof(int))      // string โ†’ int
    .ChangeType("is_active", typeof(bool))   // string โ†’ bool
    .Add("ImportedAt", typeof(DateTime))
    .WithConverter()
    .WithName("ImportedUser")
    .AsRecord()
    .Generate();

// Type-safe conversion
List<Generated.ImportedUser> users = ImportedUser.FromCollection(externalApiResponse);

๐Ÿงช Testing

Running Tests

dotnet test

Comprehensive Test Coverage

Structura is validated with 100+ comprehensive unit tests:

Test Category Test Count Description
Core Features 15 All basic TypeCombiner API features
Anonymous Types 12 Anonymous object combination and processing
EF Core Projection 18 EF Core projection result processing
Variable References 8 Anonymous type variable analysis
Type Generation Modes 6 Record, Class, Struct type generation
Edge Cases 5 Error conditions and boundary cases
Fluent API 4 Method chaining integrity
Type Safety 3 Compile-time type validation
Source Generator Integration 8 Generated type verification
Performance 3 Large-scale processing and performance
Real-World Scenarios 10 Production environment use cases
Documented Features 12 README example code validation
Integration Scenarios 15 Complex feature combinations
๐Ÿ†• Converter Extensions 20 Smart converter functionality
Add/Exclude/ChangeType 18 Property manipulation features
๐ŸŽฏ Test Results
  • Total Tests: 150+
  • Passed: 150+ โœ…
  • Failed: 0
  • Skipped: 0
  • Execution Time: < 3 seconds

๐Ÿ“ Project Structure

Structura/ โ”œโ”€โ”€ ๐Ÿ“‚ Structura/ # Main library โ”‚ โ”œโ”€โ”€ TypeCombiner.cs # Fluent API entry point โ”‚ โ”œโ”€โ”€ AnonymousTypeCombinerBuilder.cs # Anonymous type builder โ”‚ โ”œโ”€โ”€ TypeDefinitions.cs # Core type definitions โ”‚ โ””โ”€โ”€ StructuraSourceGenerator.cs # Source generator engine โ”œโ”€โ”€ ๐Ÿ“‚ Structura.Test.Console/ # Integration test console โ”‚ โ””โ”€โ”€ Program.cs # Real usage examples and demos โ”œโ”€โ”€ ๐Ÿ“‚ Structura.Tests/ # Unit test project โ”‚ โ”œโ”€โ”€ UnitTest.cs # Basic functionality unit tests โ”‚ โ”œโ”€โ”€ VariableReferenceTests.cs # Variable reference feature tests โ”‚ โ”œโ”€โ”€ EFCoreProjectionTests.cs # EF Core projection tests โ”‚ โ”œโ”€โ”€ ConverterExtensionTests.cs # Smart converter tests โ”‚ โ”œโ”€โ”€ AddFunctionalityTests.cs # Add functionality tests โ”‚ โ”œโ”€โ”€ ExcludeFunctionalityTests.cs # Exclude functionality tests โ”‚ โ”œโ”€โ”€ ChangeTypeFunctionalityTests.cs # ChangeType functionality tests โ”‚ โ””โ”€โ”€ IntegrationTests.cs # Integration and scenario tests โ””โ”€โ”€ ๐Ÿ“„ README.md # Documentation

๐Ÿ“ˆ Development Status

โœ… Completed Features

Feature Status Description
Source Generator Engine 100% โœ… Complete
Fluent API 100% โœ… Complete
Anonymous Type Support 100% โœ… Complete
Variable Reference Analysis 100% โœ… Complete
EF Core Projection Support 100% โœ… Complete
Property Add/Exclude/ChangeType 100% โœ… Complete
Type Conversion 100% โœ… Record/Class/Struct support
๐Ÿ†• Smart Converter Extensions 100% โœ… NEW! Perfect object conversion
Comprehensive Test Suite 100% โœ… 150+ tests passing

๐Ÿš€ Getting Started

1. Installation

dotnet add package Structura

2. Basic Usage

using Structura;

// Create new type from anonymous types
var userData = new { Name = "John Doe", Age = 30, Email = "john@test.com" };

TypeCombiner.Combine()
    .With(userData)
    .Add("Id", typeof(int))
    .Exclude("InternalData")  // Exclude if exists
    .WithName("User")
    .AsRecord()
    .Generate();

// Use the generated type
var user = new Generated.User("Jane Smith", 25, "jane@test.com", 1001);

3. Advanced Usage with Converter

// EF Core projection conversion
var efResult = dbContext.Products
    .Select(p => new { p.Name, p.Price, p.Category })
    .ToList();

TypeCombiner.Combine()
    .WithProjection(efResult)
    .Add("ProcessedAt", typeof(DateTime))
    .WithConverter()  // ๐Ÿ”ฅ Enable smart conversion
    .WithName("ProductDto")
    .AsRecord()
    .Generate();

// Immediate conversion available
List<Generated.ProductDto> products = ProductDto.FromCollection(efResult);

๐ŸŽจ API Reference

TypeCombiner Static Methods

Method Description Return Type
Combine() Start with anonymous types only AnonymousTypeCombinerBuilder

Fluent Methods

Method Description Chainable
.With(object) Add anonymous type โœ…
.WithProjection(IEnumerable<object>) Add EF Core projection โœ…
.Add(string, Type) Add property โœ…
.Exclude(string) Exclude property โœ…
.ChangeType(string, Type) Change property type โœ…
.WithConverter() ๐Ÿ†• Enable smart converter extensions โœ…
.WithName(string) Set generated type name โœ…
.AsRecord() Generate as record โœ…
.AsClass() Generate as class โœ…
.AsStruct() Generate as struct โœ…
.Generate() Execute type generation โŒ

๐Ÿ†• Generated Static Converter Methods

When .WithConverter() is used, the following static methods are automatically generated on the generated type itself:

Method Description Usage
.FromSingle(object) Convert single object UserDto.FromSingle(objectItem)
.FromTyped<T>(T) Convert single strongly-typed object UserDto.FromTyped(anonymousItem)
.FromCollection(IEnumerable<object>) Convert object collection UserDto.FromCollection(objectList)
.FromTypedCollection<T>(IEnumerable<T>) Convert strongly-typed collection UserDto.FromTypedCollection(anonymousList)

๐Ÿค Contributing

Issues and pull requests are welcome!

๐Ÿ“„ License

MIT License


Structura - Simplify type manipulation with smart conversion! ๐Ÿš€

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • 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.0.0 99 7/12/2025
0.9.1-beta 86 7/12/2025
0.9.0-beta 90 7/12/2025

Version 1.0.0 Release Notes:
     
     🎉 Stable Release - Production Ready:
     - Focused on proven, reliable functionality
     - Comprehensive test coverage (150+ tests)
     - Enhanced stability and predictability
     
     🚀 Core Features:
     - Anonymous type combination with .With()
     - EF Core projection support with .WithProjection()
     - Property manipulation: Add(), Exclude(), ChangeType()
     - Smart converter methods with .WithConverter()
     - Multiple type generation: Records, Classes, Structs
     
     โœจ Smart Converter Features:
     - FromCollection() for anonymous object collections
     - FromTypedCollection() for strongly-typed collections
     - FromSingle() for individual anonymous objects
     - FromTyped() for individual strongly-typed objects
     - Automatic type conversion and null handling
     
     🔧 Property Manipulation:
     - Add new properties with custom types
     - Exclude sensitive or unwanted properties
     - Change property types (e.g., decimal to string)
     - Namespace customization support
     
     🧪 Testing & Quality:
     - 150+ comprehensive unit tests
     - Property generation verification
     - Converter functionality validation
     - Integration tests for complex scenarios
     - Real-world usage pattern testing
     
     📋 API Examples:
     TypeCombiner.Combine()
       .WithProjection(efCoreResult)
       .Add("ProcessedAt", typeof(DateTime))
       .Exclude("Password")
       .ChangeType("Amount", typeof(string))
       .WithName("OrderDto")
       .WithConverter()
       .AsRecord()
       .Generate();
     
     // Usage:
     List<Generated.OrderDto> orders = OrderDto.FromCollection(efCoreResult);
     
     For documentation and examples, visit: https://github.com/dimohy/structura