4

There are configuration examples for Structure Map and Windsor: http://www.cprieto.com/index.php/2009/08/20/using-automapper-with-castle-windsor/

But I haven't found anything for Ninject.

Do you know how to translate those mappings to Ninject?

µBio
  • 10,668
  • 6
  • 38
  • 56
David Lay
  • 2,956
  • 4
  • 27
  • 48

2 Answers2

5

It's really very easy, just load this module:

public class AutoMapperModule : NinjectModule
{
    public override void Load()
    {
        Bind<ITypeMapFactory>().To<TypeMapFactory>();
        foreach (var mapper in MapperRegistry.AllMappers())
            Bind<IObjectMapper>().ToConstant(mapper);
        Bind<Configuration>().ToSelf().InSingletonScope()
            .WithConstructorArgument("mappers",
                ctx => ctx.Kernel.GetAll<IObjectMapper>());
        Bind<IConfiguration>().ToMethod(ctx => ctx.Kernel.Get<Configuration>());
        Bind<IConfigurationProvider>().ToMethod(ctx => 
            ctx.Kernel.Get<Configuration>());
        Bind<IMappingEngine>().To<MappingEngine>();
    }
}

A few things to note about this:

  • Instead of just supplying MapperRegistry.AllMappers as the constructor argument to Configuration, it actually goes and binds each individual IObjectMapper and then uses the kernel itself to get the constructor arguments in the WithConstructorArgument binding. The reason for this is so that you can load your own IObjectMapper bindings into the kernel if you decide you want to write your own custom mappers.

  • The reason for self-binding Configuration and then method-binding IConfiguration and IConfigurationProvider is that unlike Windsor, Ninject doesn't provide any first-class support for binding multiple interfaces to a single target scope, hence this hack.

That's really all there is to it. Write your container class with dependencies on IConfiguration (if you want to create new maps) and/or IMappingEngine (to actually do the mapping), and Ninject will inject them without any problems.

If you want to go ultra-loosely-coupled and have every mapping defined in its own class, then you'll probably want to take a look at the Conventions Extension for Ninject, which can do assembly scans similar to Windsor's FromAssembly. This can also load any custom IObjectMapper classes you might define in a separate library.

Aaronaught
  • 120,909
  • 25
  • 266
  • 342
  • 1
    Do you perchance have an AutoMapper v2 Module knocking about and/or a one liner explaining whether this type of strategy is viable with v2? – Ruben Bartelink Jun 12 '12 at 07:22
  • 1
    @RubenBartelink: Have you tried changing `Configuration` to `ConfigurationStore`? I think that's the only relevant change in v2; it implements the same `IConfiguration` interface and accepts the same constructor arguments as the `Configuration` in v1 did. – Aaronaught Jun 13 '12 at 23:29
  • Think `Profile` is also in the mix. Right now I have a set of them discovered via `Ninject.Extensions.Conventions` which I then feed into a `Mapper.Initialize()`. Will probably revisit when I need injection into a converter/formatter/whatever one of those is called. Hoping @jbogard might produce a canonical article and/or update para or two on how/which of v2's new abstractions fit with DI before that becomes critical. Was analyzing with a decompiler; need to read the tests (at least if how the best way to figure Ninject out is anything to go by). For now, ta for your response and this answer. – Ruben Bartelink Jun 14 '12 at 00:23
  • 1
    @RubenBartelink: I use profiles too, but I didn't get into that level of detail here because it's not pure automapper/DI code. Instead I created an `IMapRegistration` interface and had all of the implementing classes run on startup. They all take an `IProfileExpression` (still part of the v2 API) in the ctor, and then I wrote an extension method called `WithProfile` on `IBindingWithSyntax` which just creates the profile by using `WithConstructorArgument` and calling the `CreateProfile` method on a context-preserving `IConfiguration` get. Kind of a mouthful, but there it is. – Aaronaught Jun 14 '12 at 00:34
  • Sounds neat enough (though I don't have a central DLL to put such an `IMapRegistration` interface which is why I elected to use it directly. I reckon if you had the time to pull your technique into a nice "and here's how I do it with AM 2.0" answer to sit beside this one, it'd be really useful :P In the meantime, thanks for sharing the relevant details. – Ruben Bartelink Jun 14 '12 at 07:22
2
public class AutoMapperModule : NinjectModule
{
    public override void Load()
    {
        Bind<IMappingEngine>().ToMethod(ctx => Mapper.Engine);
    }
}
Dana Benson
  • 966
  • 7
  • 16