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

AdaskoTheBeAsT.AutoMapper.SimpleInjector

Seamless AutoMapper integration for SimpleInjector with automatic registration and configuration

CI CodeFactor Quality Gate Status Coverage Maintainability Rating Reliability Rating Security Rating Bugs Vulnerabilities Code Smells Duplicated Lines (%) Technical Debt Lines of Code NuGet Version NuGet Downloads GitHub stars GitHub issues GitHub last commit FOSSA Status

Why Use This?

This library eliminates the boilerplate of manually registering AutoMapper with SimpleInjector. It automatically:

  • 🔍 Scans assemblies for Profile classes 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:

This library is based on AutoMapper.Extensions.Microsoft.DependencyInjection and adapted to work seamlessly with SimpleInjector.

License

FOSSA Status


Found this helpful? Give it a ⭐ on GitHub!

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 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. 
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
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
Loading failed

- .NET 10 release