TypeSync 1.0.6
dotnet add package TypeSync --version 1.0.6
NuGet\Install-Package TypeSync -Version 1.0.6
<PackageReference Include="TypeSync" Version="1.0.6" />
<PackageVersion Include="TypeSync" Version="1.0.6" />
<PackageReference Include="TypeSync" />
paket add TypeSync --version 1.0.6
#r "nuget: TypeSync, 1.0.6"
#:package TypeSync@1.0.6
#addin nuget:?package=TypeSync&version=1.0.6
#tool nuget:?package=TypeSync&version=1.0.6
TypeSync
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.Name→CustomerName) - ✅ Collection mapping - Automatic list, array, and ICollection mapping with element type conversion
- ✅ ProjectTo - IQueryable projection for efficient EF Core queries
- ✅ Custom value resolvers - Implement
IValueResolverfor 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 objectTDestination Map<TSource, TDestination>(TSource source, MapOptions options)- Map with runtime optionsTDestination Map<TDestination>(object source)- Map using runtime typevoid Map<TSource, TDestination>(TSource source, TDestination destination)- Map to existing objectIQueryable<TDestination> ProjectTo<TDestination>(IQueryable source)- Project queryable to destination typeIQueryable<TDestination> ProjectTo<TDestination>(IQueryable source, MapOptions options)- Project with runtime options
MapperConfiguration
CreateMap<TSource, TDestination>()- Create a type mappingAddProfile<TProfile>()- Add a mapping profileAddProfilesFromAssembly(Assembly)- Auto-discover profilesCreateMapper()- Create an IMapper instanceAssertConfigurationIsValid()- Validate mappings
IMappingExpression
ForMember()- Configure individual memberReverseMap()- Create reverse mappingBeforeMap()/AfterMap()- Add actionsCondition()- Add mapping conditionConstructUsing()- 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.
- Circular Reference Protection: Both
Map()andProjectTo()detect circular references in entity graphs and type hierarchies, preventingStackOverflowExceptionwith EF Core navigation properties. - No External Access: TypeSync does not make network calls, file system access, or database connections.
- Debug Logging: Mapping failures are logged to
System.Diagnostics.Debugfor troubleshooting without exposing sensitive information.
License
MIT License
| Product | Versions 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. |
-
net8.0
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.