Structura 1.0.0
dotnet add package Structura --version 1.0.0
NuGet\Install-Package Structura -Version 1.0.0
<PackageReference Include="Structura" Version="1.0.0" />
<PackageVersion Include="Structura" Version="1.0.0" />
<PackageReference Include="Structura" />
paket add Structura --version 1.0.0
#r "nuget: Structura, 1.0.0"
#:package Structura@1.0.0
#addin nuget:?package=Structura&version=1.0.0
#tool nuget:?package=Structura&version=1.0.0
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 | Versions 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. |
-
.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