Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject AutoMapper with Autofac?

What is the proper way to inject AutoMapper to other layers?

I read this blog post , but this code cause exception below

An exception of type 'AutoMapper.AutoMapperMappingException' occurred in AutoMapper.dll but was not handled in user code

when try mapping in service layer.

List<StudentViewModel> list2 = _mapper.Map<List<StudentViewModel>>(list);

My AutoFac configuration like below:

public static class DependencyRegistration
{
    public static void Config()
    {
        var builder = new ContainerBuilder();

        builder.RegisterControllers(typeof(MvcApplication).Assembly);


        builder.RegisterType<TypeMapFactory>().As<ITypeMapFactory>();
        builder.RegisterType<ConfigurationStore>().As<ConfigurationStore>().WithParameter("mappers", MapperRegistry.Mappers).SingleInstance();
        builder.Register((ctx, t) => ctx.Resolve<ConfigurationStore>()).As<IConfiguration>().As<IConfigurationProvider>();
        builder.RegisterType<MappingEngine>().As<IMappingEngine>();

        //...
        var container = builder.Build();
        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
    }
}
like image 857
ramin_rp Avatar asked Nov 29 '15 08:11

ramin_rp


People also ask

Why you should not use AutoMapper?

1. If you use the convention-based mapping and a property is later renamed that becomes a runtime error and a common source of annoying bugs. 2. If you don't use convention-based mapping (ie you explicitly map each property) then you are just using automapper to do your projection, which is unnecessary complexity.

Is AutoMapper a singleton?

Your configuration (e.g. Automapper Profiles) are singletons. That is, they are only ever loaded once when your project runs.

When should I use AutoMapper?

Use AutoMapper to eliminate the need to write tedious boilerplate code when mapping objects in your application. AutoMapper is a popular object-to-object mapping library that can be used to map objects belonging to dissimilar types.


2 Answers

It seems that you need to use the IConfiguration object that is registered in the container to create the maps like this:

var configuration = container.Resolve<IConfiguration>();
configuration.CreateMap<Student, StudentViewModel>();

I think that you should be doing this at the start of your application.

Here is a better way (IMO) to configure things in the Config method:

public static void Config()
{
    var configuration_store = new ConfigurationStore(new TypeMapFactory(), MapperRegistry.Mappers);

    var mapping_engine = new MappingEngine(configuration_store);

    configuration_store.CreateMap<Student, StudentViewModel>();

    var builder = new ContainerBuilder();

    builder.RegisterInstance(mapping_engine).As<IMappingEngine>();

    //...
    var container = builder.Build();
    DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}

I am assuming in the last example, that your classes need access only to IMappingEngine (and not IConfiguration), since your should already setup all mappings in the Config method (or some other configuration method at application startup).

like image 118
Yacoub Massad Avatar answered Oct 07 '22 09:10

Yacoub Massad


.netcore 3 Autofac 5.1.2 AutoMapper 9.0.0 AutoMapperProfiles -> My profile name

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<AutoMapperProfiles>().As<Profile>();
    builder.Register(c => new MapperConfiguration(cfg =>
    {
        foreach (var profile in c.Resolve<IEnumerable<Profile>>())
        {
            cfg.AddProfile(profile);
        }
    })).AsSelf().SingleInstance();

    builder.Register(c => c.Resolve<MapperConfiguration>().CreateMapper(c.Resolve)).As<IMapper>().InstancePerLifetimeScope();
}
like image 21
Ali Mahmoodi Avatar answered Oct 07 '22 11:10

Ali Mahmoodi