1
votes

I organize my project into class libraries and a main caller (now is a console application, then will Apis).

  • DAL library
  • BL library
  • Models (entity) library
  • Main (console application)

I added Automapper and configured it to work between DAL and BL (Models rapresents all the entity that exposes the BL layer as point in common with other projects). That's good, but i decided to inject a IMapper via an IoC Container so i can pass the interface to constructors. Keeping in mind my architecture how can i configure Ninject for this purpose?

I'm using Automapper with "Api Instance" like this:

var config = new MapperConfiguration(cfg => {
    cfg.AddProfile<AppProfile>();
    cfg.CreateMap<Source, Dest>();
});


var mapper = config.CreateMapper();

Thanks

SOLUTION:

In the Business Logic layer i added a Ninject module:

    public class AutomapperModule : NinjectModule
    {
        public StandardKernel Nut { get; set; }

        public override void Load()
        {
            Nut = new StandardKernel(); 
            var mapperConfiguration = new MapperConfiguration(cfg => { CreateConfiguration(); });
            Nut.Bind<IMapper>().ToConstructor(c => new AutoMapper.Mapper(mapperConfiguration)).InSingletonScope(); 
        }


        public IMapper GetMapper()
        {
            return Nut.Get<IMapper>();
        }

        private MapperConfiguration CreateConfiguration()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.AddProfiles(Assembly.GetExecutingAssembly());
                cfg.AddProfiles(Assembly.Load("DataAccess"));
            });

            return config;
        }
    }

It's a mix between the examples on AutoMapper site and the answer of Jan Muncinsky.

I also added a Get method for returing the context mapper, just for helper. The client just have to call something like this:

var ioc = new AutomapperModule();
ioc.Load();
var mapper = ioc.GetMapper();

in then passing mapper to constructors...

If you have a better solution feel free to post.

1
@LucianBargaoanu, i have seen that doc, but it's not very clear for me. For example the difference between AutoMapperModule and Register. - Max Bertoli
Just to clarify, normally you don't create kernel inside of module. But you create kernel first and configure kernel with module. See my edited answer how to use Ninject modules properly. Also Get<IMapper>() is only for a demonstration purpose, most probably you'll use this method only for resolving the root object of your object graph and IMapper will be passed to constructors by Ninject automatically. So there is no need to pass something manually. - Jan Muncinsky

1 Answers

1
votes

In the simplest form it's easy as:

var kernel = new StandardKernel();
var mapperConfiguration = new MapperConfiguration(cfg => { cfg.AddProfile<AppProfile>(); });
kernel.Bind<IMapper>().ToConstructor(c => new Mapper(mapperConfiguration)).InSingletonScope();

var mapper = kernel.Get<IMapper>();

With usage of Ninject modules:

public class AutoMapperModule : NinjectModule
{
    public override void Load()
    {
        var mapperConfiguration = new MapperConfiguration(cfg => { cfg.AddProfile<AppProfile>(); });
        this.Bind<IMapper>().ToConstructor(c => new Mapper(mapperConfiguration)).InSingletonScope();
        this.Bind<Root>().ToSelf().InSingletonScope();
    }
}

public class Root
{
    public Root(IMapper mapper)
    {
    }
}

...

var kernel = new StandardKernel(new AutoMapperModule());
var root = kernel.Get<Root>();