DI examples
Lucian Bargaoanu edited this page Nov 25, 2021
·
1 revision
For those using Ninject here is an example of a Ninject module for AutoMapper
public class AutoMapperModule : NinjectModule
{
public override void Load()
{
Bind<IValueResolver<SourceEntity, DestModel, bool>>().To<MyResolver>();
var mapperConfiguration = CreateConfiguration();
Bind<MapperConfiguration>().ToConstant(mapperConfiguration).InSingletonScope();
// This teaches Ninject how to create automapper instances say if for instance
// MyResolver has a constructor with a parameter that needs to be injected
Bind<IMapper>().ToMethod(ctx =>
new Mapper(mapperConfiguration, type => ctx.Kernel.Get(type)));
}
private MapperConfiguration CreateConfiguration()
{
var config = new MapperConfiguration(cfg =>
{
// Add all profiles in current assembly
cfg.AddMaps(GetType().Assembly);
});
return config;
}
}
The workflow is as follows:
- Register your types via MyRegistrar.Register
- The MapperProvider allows you to directly inject an instance of IMapper into your other classes
- SomeProfile resolves a value using PropertyThatDependsOnIocValueResolver
- PropertyThatDependsOnIocValueResolver has IService injected into it, which is then able to be used
The ValueResolver has access to IService because we register our container via MapperConfigurationExpression.ConstructServicesUsing
public class MyRegistrar
{
public void Register(Container container)
{
// Injectable service
container.RegisterSingleton<IService, SomeService>();
// Automapper
container.RegisterSingleton(() => GetMapper(container));
}
private AutoMapper.IMapper GetMapper(Container container)
{
var mp = container.GetInstance<MapperProvider>();
return mp.GetMapper();
}
}
public class MapperProvider
{
private readonly Container _container;
public MapperProvider(Container container)
{
_container = container;
}
public IMapper GetMapper()
{
var mce = new MapperConfigurationExpression();
mce.AddMaps(typeof(SomeProfile).Assembly);
var mc = new MapperConfiguration(mce);
mc.AssertConfigurationIsValid();
return new Mapper(mc, _container.GetInstance);
}
}
public class SomeProfile : Profile
{
public SomeProfile()
{
var map = CreateMap<MySourceType, MyDestinationType>();
map.ForMember(d => d.PropertyThatDependsOnIoc, opt => opt.MapFrom<PropertyThatDependsOnIocValueResolver>());
}
}
public class PropertyThatDependsOnIocValueResolver : IValueResolver<MySourceType, object, int>
{
private readonly IService _service;
public PropertyThatDependsOnIocValueResolver(IService service)
{
_service = service;
}
int IValueResolver<MySourceType, object, int>.Resolve(MySourceType source, object destination, int destMember, ResolutionContext context)
{
return _service.MyMethod(source);
}
}
For those using Castle Windsor here is an example of an installer for AutoMapper
public class AutoMapperInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
// Register all mapper profiles
container.Register(
Classes.FromAssemblyInThisApplication(GetType().Assembly)
.BasedOn<Profile>().WithServiceBase());
// Register IConfigurationProvider with all registered profiles
container.Register(Component.For<IConfigurationProvider>().UsingFactoryMethod(kernel =>
{
return new MapperConfiguration(configuration =>
{
kernel.ResolveAll<Profile>().ToList().ForEach(configuration.AddProfile);
});
}).LifestyleSingleton());
// Register IMapper with registered IConfigurationProvider
container.Register(
Component.For<IMapper>().UsingFactoryMethod(kernel =>
new Mapper(kernel.Resolve<IConfigurationProvider>(), kernel.Resolve)));
}
}
For those using Catel.IoC here is how you register AutoMapper. First define the configuration using profiles. And then you let AutoMapper know in what assemblies those profiles are defined by registering AutoMapper in the ServiceLocator at startup:
ServiceLocator.Default.RegisterInstance(typeof(IMapper), new Mapper(CreateConfiguration()));
Configuration Creation Method:
public static MapperConfiguration CreateConfiguration()
{
var config = new MapperConfiguration(cfg =>
{
// Add all profiles in current assembly
cfg.AddMaps(GetType().Assembly);
});
return config;
}
Now you can inject AutoMapper at runtime into your services/controllers:
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper) => _mapper = mapper;
// use _mapper.Map or _mapper.ProjectTo
}