TypeSync 1.0.4

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

TypeSync

Build Status NuGet License: MIT

A lightweight, convention-based object-to-object mapping library for .NET 8. Similar to AutoMapper with a fluent API, profile support, and dependency injection integration.

Features

  • Convention-based mapping - Automatically maps properties with matching names
  • Fluent configuration API - Configure mappings using CreateMap, ForMember, ReverseMap
  • Profiles - Organize mappings into reusable profile classes
  • Flattening - Map nested properties (e.g., Customer.NameCustomerName)
  • Collection mapping - Automatic list, array, and ICollection mapping with element type conversion
  • ProjectTo - IQueryable projection for efficient EF Core queries
  • Custom value resolvers - Implement IValueResolver for complex transformations
  • Conditional mapping - Skip properties based on conditions
  • Null substitution - Provide default values for null properties
  • Before/After map actions - Execute logic before or after mapping
  • Dependency Injection - First-class support for IServiceCollection

Installation

dotnet add package TypeSync

Quick Start

Basic Usage

using TypeSync;

// Define your models
public class User
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

public class UserDto
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName { get; set; }
}

// Configure mappings
var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, UserDto>()
        .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"));
});

// Create mapper and map objects
IMapper mapper = config.CreateMapper();

var user = new User { Id = 1, FirstName = "John", LastName = "Doe", Email = "john@example.com" };
var userDto = mapper.Map<User, UserDto>(user);
// userDto.FullName == "John Doe"

Using Profiles

// Create a profile
public class UserProfile : MappingProfile
{
    public UserProfile()
    {
        CreateMap<User, UserDto>()
            .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"));
        
        CreateMap<Order, OrderDto>()
            .ReverseMap();
    }
}

// Register profiles
var config = new MapperConfiguration(cfg =>
{
    cfg.AddProfile<UserProfile>();
});

Dependency Injection (ASP.NET Core)

using TypeSync.DependencyInjection;

// In Program.cs or Startup.cs
builder.Services.AddTypeSync(cfg =>
{
    cfg.CreateMap<User, UserDto>();
    cfg.AddProfile<UserProfile>();
});

// Or auto-discover profiles from an assembly
builder.Services.AddTypeSync(typeof(Program).Assembly);

// Inject IMapper in your services
public class UserService
{
    private readonly IMapper _mapper;
    
    public UserService(IMapper mapper)
    {
        _mapper = mapper;
    }
    
    public UserDto GetUser(User user) => _mapper.Map<User, UserDto>(user);
}

Flattening

public class Order
{
    public Customer Customer { get; set; }
    public decimal Total { get; set; }
}

public class Customer
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public class OrderDto
{
    public string CustomerName { get; set; }  // Automatically mapped from Order.Customer.Name
    public string CustomerEmail { get; set; } // Automatically mapped from Order.Customer.Email
    public decimal Total { get; set; }
}

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Order, OrderDto>(); // Flattening is automatic!
});

Collection Property Mapping

TypeSync automatically maps collection properties when the element types have a defined mapping:

public class Provider
{
    public string Name { get; set; }
    public ICollection<Address> Areas { get; set; }
}

public class ProviderDto
{
    public string Name { get; set; }
    public ICollection<AddressDto> Areas { get; set; }  // Collection is mapped automatically!
}

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Provider, ProviderDto>();
    cfg.CreateMap<Address, AddressDto>().ReverseMap();
});

var provider = new Provider 
{ 
    Name = "Test",
    Areas = new List<Address> { new Address { City = "Delhi" } }
};

var dto = mapper.Map<Provider, ProviderDto>(provider);
// dto.Areas contains the mapped AddressDto items

Supported Collection Types:

  • IEnumerable<T>, ICollection<T>, IList<T>
  • List<T>, HashSet<T>
  • T[] (arrays)

ProjectTo (IQueryable Projection)

Use ProjectTo<T> for efficient database queries with Entity Framework:

using TypeSync.QueryableExtensions;

// In your repository or service
var items = await dbContext.Providers
    .Where(p => p.IsActive)
    .ProjectTo<ProviderDto>(_mapper.ConfigurationProvider)
    .ToListAsync();

This generates optimized SQL that only selects the required columns, including nested collections.

Runtime Property Ignore

Use MapOptions to ignore properties at runtime for both Map and ProjectTo:

// For Map
var options = new MapOptions("Password", "SecretKey");
var dto = mapper.Map<User, UserDto>(user, options);

// For ProjectTo
var results = query.ProjectTo<UserDto>(config, new MapOptions("Password"));

// Or via IMapper
var results = mapper.ProjectTo<UserDto>(query, new MapOptions("InternalField"));

// Fluent syntax
var options = new MapOptions().Ignore("Email").Ignore("Phone");
var dto = mapper.Map<User, UserDto>(user, options);

Advanced Features

cfg.CreateMap<User, UserDto>()
    // Custom mapping
    .ForMember(dest => dest.FullName, opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}"))
    
    // Ignore a property
    .ForMember(dest => dest.Password, opt => opt.Ignore())
    
    // Conditional mapping
    .ForMember(dest => dest.Email, opt => opt.Condition(src => src.IsEmailVisible))
    
    // Null substitution
    .ForMember(dest => dest.Nickname, opt => opt.NullSubstitute("N/A"))
    
    // Before/After map actions
    .BeforeMap((src, dest) => Console.WriteLine("Mapping started"))
    .AfterMap((src, dest) => dest.MappedAt = DateTime.UtcNow)
    
    // Custom constructor
    .ConstructUsing(src => new UserDto(src.Id))
    
    // Create reverse mapping
    .ReverseMap();

Custom Value Resolver

public class FullNameResolver : IValueResolver<User, UserDto, string>
{
    public string Resolve(User source, UserDto destination, string destMember)
    {
        return $"{source.FirstName} {source.LastName}";
    }
}

cfg.CreateMap<User, UserDto>()
    .ForMember(dest => dest.FullName, opt => opt.MapFrom<FullNameResolver>());

Configuration Validation

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<User, UserDto>();
});

// Throws if any destination members are unmapped
config.AssertConfigurationIsValid();

API Reference

IMapper

  • TDestination Map<TSource, TDestination>(TSource source) - Map to new object
  • TDestination Map<TSource, TDestination>(TSource source, MapOptions options) - Map with runtime options
  • TDestination Map<TDestination>(object source) - Map using runtime type
  • void Map<TSource, TDestination>(TSource source, TDestination destination) - Map to existing object
  • IQueryable<TDestination> ProjectTo<TDestination>(IQueryable source) - Project queryable to destination type
  • IQueryable<TDestination> ProjectTo<TDestination>(IQueryable source, MapOptions options) - Project with runtime options

MapperConfiguration

  • CreateMap<TSource, TDestination>() - Create a type mapping
  • AddProfile<TProfile>() - Add a mapping profile
  • AddProfilesFromAssembly(Assembly) - Auto-discover profiles
  • CreateMapper() - Create an IMapper instance
  • AssertConfigurationIsValid() - Validate mappings

IMappingExpression

  • ForMember() - Configure individual member
  • ReverseMap() - Create reverse mapping
  • BeforeMap() / AfterMap() - Add actions
  • Condition() - Add mapping condition
  • ConstructUsing() - Custom construction

Security Considerations

TypeSync is designed with security in mind:

  • Trusted Types Only: Only map types from trusted sources. The library uses reflection to instantiate types, so avoid mapping untrusted or dynamically loaded types.
  • Depth Limiting: Nested property resolution is limited to 10 levels to prevent stack overflow attacks.
  • No External Access: TypeSync does not make network calls, file system access, or database connections.
  • Debug Logging: Mapping failures are logged to System.Diagnostics.Debug for troubleshooting without exposing sensitive information.

License

MIT License

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

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.6 150 2/13/2026
1.0.5 126 1/17/2026
1.0.4 103 1/16/2026
1.0.3 97 1/13/2026
1.0.2 94 1/12/2026
1.0.1 95 1/12/2026
1.0.0 101 1/10/2026