类库架构下如何通过Ninject注入Automapper的IMapper?
Hey there! Let's work through setting up IMapper injection via an IoC container for your layered architecture—this will work smoothly for your current console app and transition seamlessly when you switch to an API later. Here's a step-by-step breakdown:
Since your Models project is the shared layer, and you're mapping between DAL entities (database-side) and Models entities (BL-facing), create your mapping profiles in the DAL project (they'll know the DAL's internal entities best).
For example, add a class like this to your DAL:
public class DalToModelsProfile : Profile { public DalToModelsProfile() { // Map your DAL entities to Models CreateMap<DalOrder, Order>(); CreateMap<DalCustomer, Customer>(); // Add all other mapping rules here } }
If you ever need reverse mappings (e.g., for creating/updating entities), you can add ReverseMap() to each rule, or create separate profiles—whichever keeps your code clean.
Since you're moving to an API later, using Microsoft.Extensions.DependencyInjection (the default for ASP.NET Core) is the smartest choice—it'll require zero rework when you switch. If you prefer another container like Autofac, the core logic stays the same, but I'll focus on MS DI here.
First, install the necessary NuGet packages in your Main (Console) project:
Install-Package Microsoft.Extensions.DependencyInjection Install-Package AutoMapper.Extensions.Microsoft.DependencyInjection
In your Program.cs, set up the service collection to register AutoMapper and all your layer dependencies:
using Microsoft.Extensions.DependencyInjection; var services = new ServiceCollection(); // 1. Register AutoMapper: scans ALL assemblies for your Profile classes services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies()); // 2. Register your DAL services (interface + implementation) services.AddScoped<ICustomerDal, CustomerDal>(); services.AddScoped<IOrderDal, OrderDal>(); // 3. Register your BL services (interface + implementation) services.AddScoped<ICustomerBl, CustomerBl>(); services.AddScoped<IOrderBl, OrderBl>(); // Build the service provider var serviceProvider = services.BuildServiceProvider(); // Now you can resolve your BL services and use them var customerBl = serviceProvider.GetRequiredService<ICustomerBl>(); var allCustomers = customerBl.GetActiveCustomers();
Now in your BL layer, accept IMapper via constructor injection—no need to manually create a mapper instance anymore. Here's an example BL class:
public class CustomerBl : ICustomerBl { private readonly ICustomerDal _customerDal; private readonly IMapper _mapper; // Constructor injection: IoC will pass in both dependencies public CustomerBl(ICustomerDal customerDal, IMapper mapper) { _customerDal = customerDal; _mapper = mapper; } public IEnumerable<Customer> GetActiveCustomers() { var dalCustomers = _customerDal.FetchActiveCustomers(); // Use the injected mapper to convert DAL entities to Models return _mapper.Map<IEnumerable<Customer>>(dalCustomers); } }
When you switch to an ASP.NET Core API, this setup is almost identical. You'll just move the service registration code to your Program.cs (for .NET 6+) or Startup.cs (older versions)—the AddAutoMapper call and service registrations stay exactly the same. The API will handle resolving dependencies for your controllers automatically.
If you're using Autofac instead, the process is similar:
var builder = new ContainerBuilder(); // Configure AutoMapper manually var mapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile<DalToModelsProfile>(); // Add other profiles if needed }); builder.RegisterInstance(mapperConfig.CreateMapper()).As<IMapper>(); // Register DAL/BL services builder.RegisterType<CustomerDal>().As<ICustomerDal>().InstancePerLifetimeScope(); builder.RegisterType<CustomerBl>().As<ICustomerBl>().InstancePerLifetimeScope(); var container = builder.Build();
This keeps your code decoupled, testable, and ready for your future API transition.
内容的提问来源于stack exchange,提问作者Max Bertoli

