Structura 0.9.0-beta

This is a prerelease version of Structura.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Structura --version 0.9.0-beta
                    
NuGet\Install-Package Structura -Version 0.9.0-beta
                    
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="0.9.0-beta">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Structura" Version="0.9.0-beta" />
                    
Directory.Packages.props
<PackageReference Include="Structura">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
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 0.9.0-beta
                    
#r "nuget: Structura, 0.9.0-beta"
                    
#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@0.9.0-beta
                    
#: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=0.9.0-beta&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Structura&version=0.9.0-beta&prerelease
                    
Install as a Cake Tool

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

Structura

Source Generator-Based Fluent API Type Manipulation Library

Structura is a .NET library that automatically generates new types through source generators when you define type creation and manipulation rules using a fluent API.

๐Ÿš€ Key Features

  • ๐Ÿ”„ Type Combination: Combine existing types to create new types
  • ๐ŸŽญ Anonymous Type Support: Complete anonymous type analysis including variable references
  • ๐Ÿ”— EF Core Projection Support: Convert EF Core projection results to strongly-typed types
  • โš™๏ธ Advanced Property Manipulation: Add, exclude, and change property types
  • ๐Ÿท๏ธ Diverse Type Generation: Support for Records, Classes, and Structs
  • ๐ŸŽฏ Smart Converter Extensions: Generate extension methods for seamless object conversion (NEW!)
  • ๐Ÿงช Comprehensive Testing: 100+ comprehensive unit tests

๐Ÿ“ฆ Installation

dotnet add package Structura

๐Ÿ—๏ธ Core Features

1. Type Combination

Combine existing types to create new types.

// Combine two existing types
TypeCombiner.Combine<PersonalInfo, ContactInfo>()
    .WithName("UserProfile")
    .AsRecord()
    .Generate();

// Result: Creates a UserProfile record with all properties from PersonalInfo and ContactInfo

2. Anonymous Type Support

Complete support for anonymous types and variable references.

// Direct anonymous type creation
TypeCombiner.Combine()
    .With(new { Name = "", Age = 0 })
    .With(new { Email = "", Phone = "" })
    .WithName("Contact")
    .AsRecord()
    .Generate();

// Variable reference approach (validated in actual tests)
var userInfo = new { Name = "John Doe", Age = 40, Sex = "male" };
TypeCombiner.Combine()
    .With(userInfo)
    .WithName("AnonymousUser")
    .AsClass()
    .Generate();

// Combine existing type with anonymous type
TypeCombiner.Combine<User>()
    .With(new { Department = "", Salary = 0m, Position = "" })
    .WithName("Employee")
    .AsRecord()
    .Generate();

3. EF Core Projection Support

Convert EF Core projection results to strongly-typed types.

// EF Core projection simulation
var userProjection = new List<object>
{
    new { Name = "John Doe", Email = "john@example.com" },
    new { Name = "Jane Smith", Email = "jane@example.com" }
};

TypeCombiner.Combine()
    .WithProjection(userProjection)
    .WithName("UserProjectionType")
    .AsRecord()
    .Generate();

// Dashboard data generation
var dashboardData = new List<object>
{
    new { 
        CustomerName = "John Doe", 
        TotalOrders = 12, 
        TotalSpent = 150000m,
        LastOrderDate = DateTime.Now.AddDays(-5)
    }
};

TypeCombiner.Combine()
    .WithProjection(dashboardData)
    .With(new { GeneratedAt = DateTime.Now, ReportType = "CustomerAnalysis" })
    .WithName("CustomerDashboard")
    .AsRecord()
    .Generate();

4. ๐ŸŽฏ Smart Converter Extensions (NEW!)

The game-changer for EF Core projections! Enable automatic conversion from anonymous objects to strongly-typed instances.

Basic Usage
// Step 1: Generate type with converter enabled
var efResult = dbContext.Users.Select(x => new { x.Name, x.Email }).ToList();

TypeCombiner.Combine()
    .WithProjection(efResult)
    .WithName("UserDto")
    .WithConverter()  // ๐Ÿ”ฅ This enables the magic!
    .AsRecord()
    .Generate();

// Step 2: Use the generated static converter methods directly on the type
List<Generated.UserDto> typedUsers = UserDto.FromCollection(efResult);
Generated.UserDto singleUser = UserDto.FromSingle(efResult.First());

// ๐Ÿ†• NEW! Strongly-typed anonymous object conversion
var anonymousUsers = new[] {
    new { Name = "John", Email = "john@test.com" },
    new { Name = "Jane", Email = "jane@test.com" }
};
List<Generated.UserDto> convertedUsers = UserDto.FromTypedCollection(anonymousUsers);
Generated.UserDto convertedSingle = UserDto.FromTyped(anonymousUsers.First());
Advanced Converter Scenarios
// Complex EF Core projection with additional properties
var dashboardProjection = 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(dashboardProjection)
    .With(new { 
        ReportDate = DateTime.Now,
        ReportType = "Customer Analytics",
        GeneratedBy = "System"
    })
    .WithName("CustomerAnalytics")
    .WithConverter()  // ๐Ÿ”ฅ Enable smart conversion
    .AsRecord()
    .Generate();

// Now seamlessly convert your projection results
List<Generated.CustomerAnalytics> analytics = CustomerAnalytics.FromCollection(dashboardProjection);

// Or convert individual items
Generated.CustomerAnalytics single = CustomerAnalytics.FromSingle(dashboardProjection.First());

// Convert from named types (if combining PersonalInfo + ContactInfo)
Generated.UserProfile profile1 = UserProfile.FromPersonalInfo(personalInfo);
Generated.UserProfile profile2 = UserProfile.FromContactInfo(contactInfo);
Generated.UserProfile profile3 = UserProfile.FromBoth(personalInfo, contactInfo);
```### 5. Advanced Property Manipulation

#### Property Exclusion

```csharp
TypeCombiner.From<PersonalInfo>()
    .Exclude(p => p.Password)
    .Exclude(p => p.BirthDate)
    .WithName("PublicPersonalInfo")
    .Generate();
Property Addition
TypeCombiner.From<User>()
    .Add("CreatedAt", typeof(DateTime))
    .Add("LastLoginAt", typeof(DateTime?))
    .Add("Metadata", typeof(Dictionary<string, object>))
    .WithName("ExtendedUser")
    .AsClass()
    .Generate();
Type Changes
TypeCombiner.From<Product>()
    .ChangeType(p => p.Price, typeof(string))      // decimal โ†’ string
    .ChangeType(p => p.StockQuantity, typeof(string)) // int โ†’ string
    .WithName("ProductDto")
    .Generate();
Conditional Exclusion
bool isAdmin = false;
TypeCombiner.From<PersonalInfo>()
    .ExcludeIf(p => p.Password, condition: !isAdmin)
    .WithName("ContextualUser")
    .Generate();

6. Complex Operations

All features can be used together, including the new converter functionality.

TypeCombiner.Combine<PersonalInfo, ContactInfo>()
    .Exclude<PersonalInfo>(p => p.Password)           // Exclude sensitive information
    .Add("LastLoginAt", typeof(DateTime?))            // Add new property
    .ChangeType<ContactInfo>(c => c.PhoneNumber, typeof(string)) // Change type
    .WithConverter()                                  // Enable smart conversion
    .WithName("SecureUserProfile")
    .AsRecord()
    .Generate();

// Now you can convert anonymous objects to SecureUserProfile
var anonymousData = new { FirstName = "John", Email = "john@example.com", LastLoginAt = DateTime.Now };
Generated.SecureUserProfile profile = SecureUserProfile.FromTyped(anonymousData);

๐Ÿท๏ธ Supported Type Generation

Type Method Description Converter Support
Record .AsRecord() Generate immutable records โœ… Full Support
Class .AsClass() Generate mutable classes โœ… 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

๐Ÿš€ Advanced Usage

Real-World EF Core Integration

// 1. EF Core projection query
var customerAnalytics = 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),
        FirstOrderDate = g.Min(o => o.OrderDate),
        LastOrderDate = g.Max(o => o.OrderDate)
    })
    .ToListAsync();

// 2. Generate strongly-typed DTO with converter
TypeCombiner.Combine()
    .WithProjection(customerAnalytics)
    .With(new { 
        AnalysisDate = DateTime.UtcNow,
        AnalysisType = "Customer Revenue Analysis",
        Currency = "USD"
    })
    .WithName("CustomerRevenueDto")
    .WithConverter()  // ๐Ÿ”ฅ Enable seamless conversion
    .AsRecord()
    .Generate();

// 3. Convert to strongly-typed collection
List<Generated.CustomerRevenueDto> typedAnalytics = CustomerRevenueDto.FromCollection(customerAnalytics);

// 4. Use with full IntelliSense and type safety
var topCustomers = typedAnalytics
    .Where(c => c.TotalRevenue > 10000)
    .OrderByDescending(c => c.TotalRevenue)
    .Take(10)
    .ToList();

Collection Type Support

TypeCombiner.From<User>()
    .Add("Tags", typeof(List<string>))
    .Add("Permissions", typeof(string[]))
    .Add("Properties", typeof(Dictionary<string, object>))
    .WithName("TaggedUser")
    .WithConverter()
    .Generate();

Various Data Types

var complexData = new { 
    StringValue = "test string",
    IntValue = 42,
    LongValue = 123L,
    FloatValue = 3.14f,
    DoubleValue = 2.718,
    DecimalValue = 99.99m,
    BoolValue = true,
    DateValue = DateTime.Now,
    GuidValue = Guid.NewGuid()
};

TypeCombiner.Combine()
    .With(complexData)
    .WithName("TypedData")
    .WithConverter()
    .AsStruct()
    .Generate();

// Convert with intelligent type handling
Generated.TypedData converted = TypedData.FromTyped(complexData);

๐Ÿ’ผ Real-World Scenarios

API DTO Generation

// Generate public API DTO from internal entity
TypeCombiner.From<PersonalInfo>()
    .Exclude(u => u.Password)
    .Add("PublicId", typeof(Guid))
    .WithConverter()
    .WithName("UserApiDto")
    .AsRecord()
    .Generate();

Database Migration

// Add new columns to existing table schema
TypeCombiner.From<User>()
    .Add("CreatedAt", typeof(DateTime))
    .Add("UpdatedAt", typeof(DateTime?))
    .ChangeType(u => u.IsActive, typeof(int)) // bool โ†’ int conversion
    .WithName("ModernUserTable")
    .Generate();

Complex Business Logic

// Combine multiple data sources into view model
var personalData = new { FirstName = "John", LastName = "Developer", Age = 28 };
var workData = new { Company = "TechCompany", Position = "Backend Developer", Salary = 60000m };

TypeCombiner.Combine()
    .With(personalData)
    .With(workData)
    .WithConverter()  // Enable conversion from anonymous objects
    .WithName("EmployeeProfile")
    .AsClass()
    .Generate();

// Convert combined data to strongly-typed object
var combinedAnonymous = new { 
    FirstName = "John", 
    LastName = "Developer", 
    Age = 28,
    Company = "TechCompany", 
    Position = "Backend Developer", 
    Salary = 60000m 
};
Generated.EmployeeProfile employee = EmployeeProfile.FromTyped(combinedAnonymous);

๐Ÿงช Testing

Running Tests

dotnet test

Comprehensive Test Coverage

Structura is validated with 100+ comprehensive unit tests:

Test Category Test Count Description
Core Functionality 11 tests All basic TypeCombiner API features
Anonymous Types 4 tests Anonymous object combination and processing
Single Type Builder 7 tests All From<T>() method functionality
Complex Scenarios 4 tests Multi-feature combination use cases
EF Core Projection 13 tests EF Core projection result processing
Variable References 9 tests Anonymous type variable analysis
Type Generation Modes 2 tests Record, Class, Struct type generation
Edge Cases 4 tests Error conditions and boundary cases
Fluent API 3 tests Method chaining integrity
Type Safety 3 tests Compile-time type validation
Source Generator Integration 6 tests Generated type verification
Performance 2 tests Large-scale processing and performance
Real-World Scenarios 5 tests Production environment use cases
Documented Features 8 tests README example code validation
Integration Scenarios 12 tests Complex feature combinations
๐Ÿ†• Converter Extensions 15 tests Smart converter functionality
๐ŸŽฏ Test Results
  • Total Tests: 100+
  • Passed: 100+ โœ…
  • Failed: 0
  • Skipped: 0
  • Execution Time: < 2 seconds

๐Ÿ“ Project Structure

Structura/
โ”œโ”€โ”€ ๐Ÿ“‚ Structura/                     # Main library
โ”‚   โ”œโ”€โ”€ TypeCombiner.cs               # Fluent API entry point
โ”‚   โ”œโ”€โ”€ TypeCombinerBuilder.cs        # Multi-type combination builder
โ”‚   โ”œโ”€โ”€ 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
โ”‚   โ”œโ”€โ”€ IntegrationTests.cs          # Integration and scenario tests
โ”‚   โ””โ”€โ”€ TestModels.cs                # Test model classes
โ””โ”€โ”€ ๐Ÿ“„ 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 100% โœ… Complete
Type Conversion 100% โœ… Record/Class/Struct support
๐Ÿ†• Smart Converter Extensions 100% โœ… NEW! Seamless object conversion
Comprehensive Test Suite 100% โœ… 100+ tests passing

๐Ÿ”ง Partially Completed Features

Feature Status Notes
Existing Type Property Inheritance 95% ๐Ÿ”„ Basic behavior complete
Advanced Property Manipulation 90% ๐Ÿ”„ Some complex scenarios limited

๐Ÿš€ Getting Started

1. Installation

dotnet add package Structura

2. Basic Usage

using Structura;

// Create new type from anonymous types
TypeCombiner.Combine()
    .With(new { Name = "", Age = 0 })
    .With(new { Email = "", Phone = "" })
    .WithName("Contact")
    .AsRecord()
    .Generate();

// Use the generated type
var contact = new Generated.Contact("John Doe", 30, "john@example.com", "555-1234");

3. Advanced Usage with Converter

// Add properties to existing type with converter support
TypeCombiner.From<User>()
    .Add("CreatedAt", typeof(DateTime))
    .Add("Metadata", typeof(Dictionary<string, object>))
    .WithConverter()  // ๐Ÿ”ฅ Enable smart conversion
    .WithName("ExtendedUser")
    .AsClass()
    .Generate();

// Convert anonymous object to strongly-typed instance
var anonymousUser = new {
    Name = "Developer",
    Age = 25,
    Email = "dev@example.com",
    CreatedAt = DateTime.Now,
    Metadata = new Dictionary<string, object>()
};

Generated.ExtendedUser typedUser = ExtendedUser.FromTyped(anonymousUser);

๐ŸŽจ API Reference

TypeCombiner Static Methods

Method Description Return Type
Combine<T1, T2>() Combine two types TypeCombinerBuilder<T1, T2>
Combine<T>() Start with single type TypeCombinerBuilder<T>
Combine() Start with anonymous types only AnonymousTypeCombinerBuilder
From<T>() Start with existing type as base SingleTypeCombinerBuilder<T>

Fluent Methods

Method Description Chainable
.With(object) Add anonymous type โœ…
.WithProjection(IEnumerable<object>) Add EF Core projection โœ…
.Add(string, Type) Add property โœ…
.Exclude(Expression) Exclude property โœ…
.ExcludeIf(Expression, bool) Conditionally exclude property โœ…
.ChangeType(Expression, 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 UserProjectionType.FromSingle(objectItem)
.FromTyped<T>(T) Convert single strongly-typed object UserProjectionType.FromTyped(anonymousItem)
.FromCollection(IEnumerable<object>) Convert object collection UserProjectionType.FromCollection(objectList)
.FromTypedCollection<T>(IEnumerable<T>) Convert strongly-typed collection UserProjectionType.FromTypedCollection(anonymousList)
.FromSourceType(SourceType) Convert from source type CombinedType.FromPersonalInfo(personalInfo)
.FromBoth(SourceType1, SourceType2) Convert from multiple sources CombinedType.FromBoth(personal, contact)

๐Ÿค 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 0.9.0-beta Release Notes:
     
     🚀 New Features:
     - Complete anonymous type support with variable reference analysis
     - EF Core projection result type generation
     - Advanced property manipulation (Add, Exclude, ChangeType)
     - Support for Records, Classes, and Structs generation
     - 🆕 Smart Converter Extensions: Revolutionary .WithConverter() method for seamless object conversion
     - Comprehensive fluent API with method chaining
     
     🔧 Improvements:
     - Enhanced source generator performance
     - Better type inference and analysis
     - Improved error handling and validation
     - 100+ comprehensive unit tests including converter functionality
     
     🎯 Beta Features:
     - Variable reference analysis for anonymous types
     - EF Core projection support with smart conversion
     - Complex type combination scenarios
     - Intelligent type mapping and conversion
     
     🌟 Smart Converter Highlights:
     - Direct static methods on generated types: UserDto.FromCollection()
     - Strongly-typed anonymous object conversion: UserDto.FromTypedCollection()
     - Individual object conversion: UserDto.FromTyped(), UserDto.FromSingle()
     - Named type converters: CombinedType.FromSourceType(), CombinedType.FromBoth()
     - Intelligent type mapping with null safety
     - Support for primitives, collections, and complex types
     - Case-insensitive property matching
     - Compile-time type safety with full IntelliSense
     
     📋 Known Issues:
     - Some advanced property manipulation scenarios may be limited
     - Existing type property inheritance is at 95% completion
     
     For full documentation and examples, visit: https://github.com/dimohy/structura