Refbesh.CastBesh 1.0.1

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

CastBesh

NuGet License: MIT

CastBesh is a high-performance object mapping library that brings native C# cast syntax to complex type transformations. Map objects as naturally as casting primitives!

🚀 Why CastBesh?

Transform this verbose mapping:

var dto = mapper.Map<UserEntity, UserDto>(userEntity);

Into this elegant, native C# syntax:

var dto = (UserDto)userEntity;  // Just like (int)myDouble!

One simple line per cast direction - that's all it takes!

✨ Features

  • Native Cast Syntax: Use explicit cast operators (TargetType)source just like primitive types
  • One-Line Setup: Add one simple cast operator per direction - done!
  • High Performance: Expression tree compilation (10-50x faster than reflection)
  • Multi-Framework: Supports .NET 6, 7, 8, and 9
  • Fluent Configuration: Easy-to-use configuration API
  • Async Support: Built-in asynchronous mapping capabilities
  • Collection Mapping: Optimized batch operations for collections
  • Alternative Syntax: .As<T>() extension method when you can't modify types
  • Type Safety: Compile-time type checking
  • Zero Reflection: Compiled mappers for maximum speed

📦 Installation

dotnet add package Refbesh.CastBesh

Or via NuGet Package Manager:

Install-Package Refbesh.CastBesh

🎯 Quick Start

1. Define Your Models with Cast Operators

Add one line per cast direction to your classes:

using Refbesh.CastBesh.Casting;

public class UserEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public bool IsActive { get; set; }

    // Add cast operator - just one line!
    public static explicit operator UserDto(UserEntity source)
        => CastEngine.Cast<UserEntity, UserDto>(source);
}

public class UserDto
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public string Email { get; set; }
    public string Status { get; set; }
}

2. Configure Mappings (Startup)

using Refbesh.CastBesh;

CastBeshStartup.Configure(config =>
{
    config.CreateMap<UserEntity, UserDto>()
        .WithSync(entity => new UserDto
        {
            Id = entity.Id,
            FullName = $"{entity.FirstName} {entity.LastName}",
            Email = entity.Email,
            Status = entity.IsActive ? "Active" : "Inactive"
        })
        .Build();
});

3. Use Native Cast Syntax Anywhere!

var userEntity = new UserEntity 
{ 
    Id = 1, 
    FirstName = "John", 
    LastName = "Doe",
    Email = "john@example.com",
    IsActive = true 
};

// Cast like a primitive type!
var userDto = (UserDto)userEntity;

Console.WriteLine(userDto.FullName); // "John Doe"
Console.WriteLine(userDto.Status);   // "Active"

📚 Usage Examples

Bidirectional Mapping

public class UserEntity
{
    // Properties...
    
    public static explicit operator UserDto(UserEntity source)
        => CastEngine.Cast<UserEntity, UserDto>(source);
}

public class UserDto
{
    // Properties...
    
    // Reverse cast
    public static explicit operator UserEntity(UserDto source)
        => CastEngine.Cast<UserDto, UserEntity>(source);
}

// Usage - works both ways!
var dto = (UserDto)entity;
var entity = (UserEntity)dto;

Multiple Target Types

public class UserEntity
{
    // Properties...
    
    // Cast to multiple types
    public static explicit operator UserDto(UserEntity source)
        => CastEngine.Cast<UserEntity, UserDto>(source);
    
    public static explicit operator UserListDto(UserEntity source)
        => CastEngine.Cast<UserEntity, UserListDto>(source);
}

// Usage
var fullDto = (UserDto)userEntity;
var listDto = (UserListDto)userEntity;

Collection Mapping

var entities = new List<UserEntity> { /* ... */ };

// Option 1: LINQ with cast syntax
var dtos = entities.Select(e => (UserDto)e).ToList();

// Option 2: Optimized extension method
var dtos = entities.CastToList<UserEntity, UserDto>();

Inline Casting in Methods

public void ProcessUser(UserDto dto)
{
    Console.WriteLine($"Processing: {dto.FullName}");
}

// Cast inline in method calls - just like primitives!
ProcessUser((UserDto)userEntity);

LINQ Integration

var activeDtos = users
    .Where(u => u.IsActive)
    .Select(u => (UserDto)u)
    .OrderBy(d => d.FullName)
    .ToList();

Async Mapping

// Configure with async support
config.CreateMap<UserEntity, UserDto>()
    .WithSync(entity => /* sync mapping */)
    .WithAsync(async (entity, ct) =>
    {
        await Task.Delay(10, ct); // Simulate async work
        return new UserDto { /* ... */ };
    })
    .Build();

// Use async casting
var dto = await CastEngine.CastAsync<UserEntity, UserDto>(userEntity);

Alternative Syntax (When You Can't Modify Types)

If you can't add cast operators to a type (e.g., third-party library), use extension methods:

using Refbesh.CastBesh.Extensions;

// Use .As<T>() extension method
var dto = userEntity.As<UserDto>();

// Or fluent syntax
var dto = userEntity.ToCastable().To<UserDto>();

// Safe casting
if (userEntity.TryAs<UserDto>(out var dto))
{
    Console.WriteLine($"Success: {dto.FullName}");
}

🔧 Advanced Features

Custom Mappers

public class CustomUserMapper : CastMapperBase<UserEntity, UserDto>
{
    public override UserDto Map(UserEntity source)
    {
        // Custom mapping logic
        return new UserDto { /* ... */ };
    }
}

config.RegisterMapper(new CustomUserMapper());

Auto-Mapping (Convention-Based)

For simple property-to-property mappings:

using Refbesh.CastBesh.Registry;

// Automatically map properties with matching names
CastMapperRegistry.Instance.RegisterAutoMap<SourceType, DestinationType>();

Diagnostics & Performance Monitoring

using Refbesh.CastBesh.Diagnostics;

MappingDiagnostics.Enabled = true;

// Perform mappings...
var dto = (UserDto)entity;

var metrics = MappingDiagnostics.GetMetrics<UserEntity, UserDto>();
Console.WriteLine($"Average: {metrics.AverageDuration.TotalMilliseconds}ms");
Console.WriteLine($"Success Rate: {metrics.SuccessRate}%");

Configuration Validation

using Refbesh.CastBesh.Configuration;

var result = ConfigurationValidator.Validate<UserEntity, UserDto>();

if (!result.IsValid)
{
    Console.WriteLine("Validation Errors:");
    foreach (var error in result.Errors)
        Console.WriteLine($"  - {error}");
}

Batch Async Processing

var entities = GetLargeList(); // 10,000+ items

// Process in batches to control memory
var dtos = await entities.CastToListAsync<UserEntity, UserDto>(
    batchSize: 100,
    cancellationToken: cancellationToken
);

⚡ Performance

CastBesh uses compiled expression trees for mapping, providing performance comparable to hand-written code:

  • 10-50x faster than reflection-based mapping
  • Zero allocation for struct keys in registry
  • Aggressive inlining for hot paths
  • Optimized collection processing
// Benchmark: 10,000 mappings
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000; i++)
{
    var dto = (UserDto)userEntity;
}
sw.Stop();
// Typical result: ~2-5ms for 10,000 mappings

🎓 Best Practices

1. Configure Once at Startup

// In Program.cs or Startup.cs
CastBeshStartup.Configure(config =>
{
    config.CreateMap<Entity1, Dto1>().WithSync(/* ... */).Build();
    config.CreateMap<Entity2, Dto2>().WithSync(/* ... */).Build();
    // Configure all mappings here
});

2. One Line Per Cast Direction

// Keep cast operators simple - just delegate to CastEngine
public static explicit operator UserDto(UserEntity source)
    => CastEngine.Cast<UserEntity, UserDto>(source);

3. Use Expression Body for Cast Operators

// ✅ Preferred - clean and concise
public static explicit operator UserDto(UserEntity source)
    => CastEngine.Cast<UserEntity, UserDto>(source);

// ❌ Avoid - unnecessary verbosity
public static explicit operator UserDto(UserEntity source)
{
    return CastEngine.Cast<UserEntity, UserDto>(source);
}

4. Organize Mappings by Feature

// UserMappingProfile.cs
public static class UserMappingProfile
{
    public static void Configure(CastConfiguration config)
    {
        config.CreateMap<User, UserDto>().WithSync(/* ... */).Build();
        config.CreateMap<User, UserListDto>().WithSync(/* ... */).Build();
    }
}

// In Startup
CastBeshStartup.Configure(config =>
{
    UserMappingProfile.Configure(config);
    ProductMappingProfile.Configure(config);
});

💡 When to Use CastBesh

✅ Great For:

  • APIs where you frequently convert between entities and DTOs
  • Clean Architecture / Onion Architecture projects
  • Domain-Driven Design (DDD) applications
  • Applications with many similar type conversions
  • Projects where readability and maintainability matter

❌ Not Needed For:

  • Very simple projects with minimal type conversions
  • When types already have natural inheritance relationships
  • When you only need to map 1-2 types in your entire application

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE.txt file for details.

💡 Comparison with Other Mappers

AutoMapper

// AutoMapper
var dto = _mapper.Map<UserDto>(userEntity);

// CastBesh
var dto = (UserDto)userEntity;

CastBesh Advantages:

  • Native C# syntax (no dependency injection needed)
  • Compile-time safety
  • More explicit and readable
  • Better IDE support

Mapster

// Mapster
var dto = userEntity.Adapt<UserDto>();

// CastBesh
var dto = (UserDto)userEntity;

CastBesh Advantages:

  • Uses standard C# cast operators
  • More intuitive for C# developers
  • One-line setup per cast direction

🎉 Inspiration

Inspired by the simplicity and elegance of primitive type casting in C#:

// Primitive casting - simple and intuitive
double myDouble = 10.7;
int myInt = (int)myDouble;

// CastBesh - same simplicity for complex types!
UserEntity userEntity = GetUser();
UserDto userDto = (UserDto)userEntity;

Made with ❤️ by Refbesh

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  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 is compatible.  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 is compatible.  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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net6.0

    • No dependencies.
  • net7.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.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.1 210 10/2/2025

v1.0.1: Updated README with improved documentation