AdaskoTheBeAsT.AutoMapper.SimpleInjector
14.0.0
dotnet add package AdaskoTheBeAsT.AutoMapper.SimpleInjector --version 14.0.0
NuGet\Install-Package AdaskoTheBeAsT.AutoMapper.SimpleInjector -Version 14.0.0
<PackageReference Include="AdaskoTheBeAsT.AutoMapper.SimpleInjector" Version="14.0.0" />
<PackageVersion Include="AdaskoTheBeAsT.AutoMapper.SimpleInjector" Version="14.0.0" />
<PackageReference Include="AdaskoTheBeAsT.AutoMapper.SimpleInjector" />
paket add AdaskoTheBeAsT.AutoMapper.SimpleInjector --version 14.0.0
#r "nuget: AdaskoTheBeAsT.AutoMapper.SimpleInjector, 14.0.0"
#:package AdaskoTheBeAsT.AutoMapper.SimpleInjector@14.0.0
#addin nuget:?package=AdaskoTheBeAsT.AutoMapper.SimpleInjector&version=14.0.0
#tool nuget:?package=AdaskoTheBeAsT.AutoMapper.SimpleInjector&version=14.0.0
AdaskoTheBeAsT.AutoMapper.SimpleInjector
Seamless AutoMapper integration for SimpleInjector with automatic registration and configuration
Why Use This?
This library eliminates the boilerplate of manually registering AutoMapper with SimpleInjector. It automatically:
- 🔍 Scans assemblies for
Profileclasses and registers them - 🔄 Auto-registers all AutoMapper extensions (
ITypeConverter,IValueResolver,IMemberValueResolver,IValueConverter,IDestinationFactory,ICondition,IPreCondition,IMappingAction) - 💉 Handles dependency injection for your custom converters and resolvers
- ⚙️ Configures everything with a single fluent API call
- 🎯 Supports .NET 8, 9, and 10
Installation
dotnet add package AdaskoTheBeAsT.AutoMapper.SimpleInjector
1. Create Your Mapping Profiles
public class UserProfile : Profile
{
public UserProfile()
{
CreateMap<UserEntity, UserDto>();
CreateMap<UserDto, UserEntity>();
}
}
2. Register AutoMapper with SimpleInjector
using AdaskoTheBeAsT.AutoMapper.SimpleInjector;
using SimpleInjector;
var container = new Container();
// Option 1: Scan by marker type (recommended)
container.AddAutoMapper(typeof(UserProfile));
// Option 2: Scan multiple assemblies
container.AddAutoMapper(typeof(UserProfile).Assembly, typeof(OrderProfile).Assembly);
// Option 3: Scan with configuration
container.AddAutoMapper(cfg =>
{
cfg.WithMapperAssemblyMarkerTypes(typeof(UserProfile));
cfg.AsScoped(); // Change lifestyle if needed
});
3. Use IMapper in Your Services
public class UserService
{
private readonly IMapper _mapper;
public UserService(IMapper mapper)
{
_mapper = mapper;
}
public UserDto GetUser(UserEntity entity)
{
return _mapper.Map<UserDto>(entity);
}
}
What Gets Registered?
This library automatically registers the following with your container:
| Type | Registration | Description |
|---|---|---|
IConfigurationProvider |
Singleton | AutoMapper configuration (not registered when using custom mapper instance) |
IMapper |
Singleton* | Main mapper instance |
ITypeConverter<,> |
Transient | Custom type converters |
IValueConverter<,> |
Transient | Custom value converters |
IValueResolver<,,> |
Transient | Custom value resolvers |
IMemberValueResolver<,,,> |
Transient | Custom member resolvers |
IDestinationFactory<,> |
Transient | Custom destination object factories (ConstructUsing<T>()) |
ICondition<,,> |
Transient | Custom member conditions (Condition<T>()) |
IPreCondition<,> |
Transient | Custom member pre-conditions (PreCondition<T>()) |
IMappingAction<,> |
Transient | Custom mapping actions |
*Lifestyle is configurable (Singleton/Scoped/Transient)
Usage Examples
Basic Usage - Scan by Type
container.AddAutoMapper(typeof(UserProfile), typeof(OrderProfile));
Scan Assemblies from Your Solution
public static class AutoMapperConfigurator
{
private const string NamespacePrefix = "YourCompany.YourProject";
public static void Configure(Container container)
{
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
var assemblies = new List<Assembly>();
var mainAssembly = typeof(AutoMapperConfigurator).Assembly;
var refAssemblies = mainAssembly.GetReferencedAssemblies();
foreach (var assemblyName in refAssemblies
.Where(a => a.FullName.StartsWith(NamespacePrefix, StringComparison.OrdinalIgnoreCase)))
{
var assembly = loadedAssemblies.Find(l => l.FullName == assemblyName.FullName)
?? AppDomain.CurrentDomain.Load(assemblyName);
assemblies.Add(assembly);
}
container.AddAutoMapper(assemblies);
}
}
Using Custom Resolvers with Dependency Injection
Your custom resolvers can have dependencies automatically injected:
public class DependencyResolver : IValueResolver<Source, Dest, int>
{
private readonly ISomeService _service;
public DependencyResolver(ISomeService service)
{
_service = service;
}
public int Resolve(Source source, Dest dest, int destMember, ResolutionContext context)
{
return _service.Modify(destMember);
}
}
// Registration
container.Register<ISomeService, SomeService>();
container.AddAutoMapper(typeof(DependencyResolver));
// The resolver will automatically get ISomeService injected!
Advanced Configuration
Change IMapper Lifestyle (Scoped/Transient)
container.AddAutoMapper(cfg =>
{
cfg.WithMapperAssemblyMarkerTypes(typeof(UserProfile));
cfg.AsScoped(); // Use Scoped lifestyle
// or cfg.AsTransient(); // Use Transient lifestyle
// or cfg.AsSingleton(); // Default: Singleton
});
Custom Mapper Configuration
Add custom mappings programmatically:
container.AddAutoMapper(cfg =>
{
cfg.WithAssembliesToScan(assemblies);
cfg.WithMapperConfigurationExpressionAction((container, expression) =>
{
// Add custom mappings
expression.CreateMap<Foo, Bar>().ReverseMap();
// Configure global settings
expression.AllowNullCollections = true;
});
});
Using Custom IMapper Implementation
public class MyCustomMapper : IMapper
{
// Your custom implementation
}
container.AddAutoMapper(cfg =>
{
cfg.Using<MyCustomMapper>();
cfg.WithMapperAssemblyMarkerTypes(typeof(UserProfile));
});
Unit Testing with Mock IMapper
Perfect for unit tests using Moq or similar frameworks.
When using a custom mapper instance via Using(Func<IMapper>), IConfigurationProvider is not registered
in the container, since the custom mapper fully replaces the default AutoMapper pipeline:
var testMapper = new Mock<IMapper>();
testMapper.Setup(m => m.Map<UserDto>(It.IsAny<UserEntity>()))
.Returns(new UserDto { Id = 1, Name = "Test User" });
container.AddAutoMapper(cfg =>
{
cfg.Using(() => testMapper.Object);
cfg.WithMapperAssemblyMarkerTypes(typeof(UserProfile));
});
Setting AutoMapper License Key
If you're using AutoMapper's premium features:
container.AddAutoMapper(cfg =>
{
cfg.WithLicenseKey("your-license-key");
cfg.WithMapperAssemblyMarkerTypes(typeof(UserProfile));
});
Common Patterns
Using IMapper.Map
Inject IMapper into your services to perform runtime mapping:
public class EmployeesController
{
private readonly IMapper _mapper;
private readonly IEmployeeRepository _repository;
public EmployeesController(IMapper mapper, IEmployeeRepository repository)
{
_mapper = mapper;
_repository = repository;
}
public EmployeeDto GetEmployee(int id)
{
var employee = _repository.GetById(id);
return _mapper.Map<EmployeeDto>(employee);
}
public IEnumerable<EmployeeDto> GetAllEmployees()
{
var employees = _repository.GetAll();
return _mapper.Map<IEnumerable<EmployeeDto>>(employees);
}
}
Using ProjectTo for Entity Framework / LINQ
For efficient database queries, use ProjectTo to project directly to DTOs:
public class OrderService
{
private readonly DbContext _dbContext;
private readonly IConfigurationProvider _configurationProvider;
public OrderService(DbContext dbContext, IConfigurationProvider configurationProvider)
{
_dbContext = dbContext;
_configurationProvider = configurationProvider;
}
// Option 1: Using IConfigurationProvider directly (recommended)
public async Task<List<OrderDto>> GetOrdersAsync()
{
return await _dbContext.Orders
.ProjectTo<OrderDto>(_configurationProvider)
.ToListAsync();
}
}
Or inject IMapper instead:
public class OrderService
{
private readonly DbContext _dbContext;
private readonly IMapper _mapper;
public OrderService(DbContext dbContext, IMapper mapper)
{
_dbContext = dbContext;
_mapper = mapper;
}
// Option 2: Using IMapper.ConfigurationProvider
public async Task<List<OrderDto>> GetOrdersAsync()
{
return await _dbContext.Orders
.ProjectTo<OrderDto>(_mapper.ConfigurationProvider)
.ToListAsync();
}
}
API Reference
AddAutoMapper Extension Methods
| Method | Description |
|---|---|
AddAutoMapper(params Type[]) |
Register AutoMapper by scanning assemblies containing the specified types |
AddAutoMapper(params Assembly[]) |
Register AutoMapper by scanning the specified assemblies |
AddAutoMapper(IEnumerable<Assembly>) |
Register AutoMapper by scanning the specified assemblies |
AddAutoMapper(IEnumerable<Type>) |
Register AutoMapper by scanning assemblies containing the specified types |
AddAutoMapper(Action<AutoMapperSimpleInjectorConfiguration>) |
Register AutoMapper with custom configuration |
Configuration Methods
| Method | Description |
|---|---|
WithMapperAssemblyMarkerTypes(params Type[]) |
Specify types to mark assemblies for scanning (eagerly materialized, throws on null) |
WithAssembliesToScan(IEnumerable<Assembly>) |
Specify assemblies to scan directly (defensively copied, throws on null) |
Using<TMapper>() |
Use a custom IMapper implementation |
Using(Func<IMapper>) |
Use a factory function to create IMapper (useful for testing; skips IConfigurationProvider registration) |
AsSingleton() |
Register IMapper as Singleton (default) |
AsScoped() |
Register IMapper as Scoped |
AsTransient() |
Register IMapper as Transient |
WithMapperConfigurationExpressionAction(...) |
Add custom mapper configuration |
WithLicenseKey(string) |
Set AutoMapper license key (only applied when non-null/non-empty) |
Requirements
- .NET 8.0, 9.0, or 10.0
- AutoMapper 15.1.0+
- SimpleInjector 5.5.0+
Running Tests Locally
dotnet test
The test suite needs an AutoMapper license key. AutoMapper resolves it from the environment
(AUTOMAPPER_LICENSE_KEY, then the shared LUCKYPENNY_LICENSE_KEY) unless a key is passed
explicitly via WithLicenseKey(...). In CI the value comes from the AUTOMAPPER_LICENSE_KEY
GitHub secret (see .github/workflows/ci.yml).
To supply it locally, copy the template and fill in your key:
cp .env.example .env
AUTOMAPPER_LICENSE_KEY=your-license-key
.env is git ignored, so the key never lands in the repository. A module initializer in the test
project (TestEnvironment) uses dotenv.net to probe
upwards from the test output directory for the nearest .env and exports every KEY=VALUE entry
into the test process before the first MapperConfiguration is built. Variables that are already
set in the environment are never overwritten, so CI values always win over the file.
This works the same for dotnet test and for the test runners in Visual Studio, Rider, and VS Code.
If you prefer not to keep a file in the working tree, set a user-level environment variable instead
(setx AUTOMAPPER_LICENSE_KEY "your-license-key" on Windows) and restart your IDE or shell.
Credits
Special thanks to:
- Jimmy Bogard for creating AutoMapper
- Steven van Deursen for creating SimpleInjector
This library is based on AutoMapper.Extensions.Microsoft.DependencyInjection and adapted to work seamlessly with SimpleInjector.
License
Found this helpful? Give it a ⭐ on GitHub!
| 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 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 is compatible. 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. |
-
net10.0
- AutoMapper (>= 16.2.0 && < 17.0.0)
- SimpleInjector (>= 5.6.0 && < 6.0.0)
-
net8.0
- AutoMapper (>= 16.2.0 && < 17.0.0)
- SimpleInjector (>= 5.6.0 && < 6.0.0)
-
net9.0
- AutoMapper (>= 16.2.0 && < 17.0.0)
- SimpleInjector (>= 5.6.0 && < 6.0.0)
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 |
|---|---|---|
| 14.0.0 | 36 | 8/2/2026 |
| 13.1.0 | 152 | 4/4/2026 |
| 13.0.0 | 470 | 11/11/2025 |
| 12.0.0 | 291 | 10/26/2025 |
| 11.0.0 | 644 | 2/15/2025 |
| 10.0.0 | 330 | 11/13/2024 |
| 9.2.0 | 466 | 8/18/2024 |
| 9.1.0 | 313 | 5/27/2024 |
| 8.0.1 | 613 | 1/27/2024 |
| 8.0.0 | 660 | 11/29/2023 |
| 7.0.1 | 1,286 | 1/22/2023 |
| 7.0.0 | 1,045 | 11/13/2022 |
| 6.0.0 | 1,098 | 10/17/2022 |
| 5.1.0 | 1,101 | 7/24/2022 |
| 5.0.1 | 1,210 | 2/8/2022 |
| 5.0.0 | 992 | 1/6/2022 |
| 4.2.2 | 1,422 | 7/24/2021 |
| 4.2.1 | 1,017 | 6/27/2021 |
| 4.2.0 | 1,249 | 3/7/2021 |
| 4.1.1 | 1,246 | 1/16/2021 |
- .NET 10 release