views:

167

answers:

3

I am having trouble injecting AutoMapper into an ASP.NET MVC 2 application using Ninject. I used Jimmy Bogard's post on AutoMapper and StructureMap type Configuration as a guide.

public class AutoMapperModule : NinjectModule
{
    public override void Load()
    {
        Bind<ITypeMapFactory>().To<TypeMapFactory>();
        Bind<Configuration>().ToSelf().InSingletonScope().WithConstructorArgument("mapper", MapperRegistry.AllMappers);
        Bind<IConfiguration>().To<Configuration>();
        Bind<IConfigurationProvider>().To<Configuration>();
        Bind<IMappingEngine>().To<MappingEngine>();
    }
}

Ninject throws an exception when resolving Configuration.

Error activating IObjectMapper No matching bindings are available, and the type is not self-bindable. Activation path:
3) Injection of dependency IObjectMapper into parameter mappers of constructor of type Configuration

Update

This is now working using the following binding:

    Bind<ITypeMapFactory>().To<TypeMapFactory>();
    Bind<Configuration>().ToConstant(new Configuration(Kernel.Get<ITypeMapFactory>(), MapperRegistry.AllMappers())).InSingletonScope();
    Bind<IConfiguration>().ToMethod(c => c.Kernel.Get<Configuration>());
    Bind<IConfigurationProvider>().ToMethod(c => c.Kernel.Get<Configuration>());
    Bind<IMappingEngine>().To<MappingEngine>();

I published the module on GitHub. AutoMapper.Ninject. More information on my blog: http://binaryspeakeasy.com/2010/09/automapper-ninject/

A: 

(Not checked but translated from post:-

  ForRequestedType<Configuration>()
        .CacheBy(InstanceScope.Singleton)
        .TheDefault.Is.OfConcreteType<Configuration>()
        .CtorDependency<IEnumerable<IObjectMapper>>().Is(expr => expr.ConstructedBy(MapperRegistry.AllMappers));

would be something like:

Bind<Configuration>.ToSelf().WithConstructorArgument( MapperRegistry.AllMappers);

(you'll probably need to add an arg name)

(The MapperRegistry,.AllMappers bit is:-

public static class MapperRegistry
{
      public static Func<IEnumerable<IObjectMapper>> AllMappers = () => new IObjectMapper[]
       {
           new CustomTypeMapMapper(),

...

           new TypeConverterMapper(),
           new NullableMapper(),
       };
  }
Ruben Bartelink
Ruben,I have already defined the Constructor binding as: Bind<Configuration>().ToSelf().InSingletonScope().WithConstructorArgument("mapper", MapperRegistry.AllMappers);
Corey Coto
A: 

I got it working but it doesn't feel very clean creating an instance of the Configuration class. Any suggestions to clean it up further.

        Bind<ITypeMapFactory>().To<TypeMapFactory>();
        Bind<Configuration>().ToConstant(new Configuration(Kernel.Get<ITypeMapFactory>(), MapperRegistry.AllMappers())).InSingletonScope();
        Bind<IConfiguration>().ToMethod(c => c.Kernel.Get<Configuration>());
        Bind<IConfigurationProvider>().ToMethod(c => c.Kernel.Get<Configuration>());
        Bind<IMappingEngine>().To<MappingEngine>();
Corey Coto
@Corey Coto: best to edit this into your question. In general I'd say you're overusing `Bind<IX>().ToMethod(c => c.Kernel.Get<X>()`. Just use `Bind<IX>().To<X>()`
Ruben Bartelink
Ditto `Bind<Configuration>().ToConstant(new Configuration(Kernel.Get<ITypeMapFactory>(), MapperRegistry.AllMappers())).InSingletonScope();` should map to `.To<>.WithConstructorArgument`....
Ruben Bartelink
A: 

It might also be a good idea to introduce a mapping facade. Instead of passing IMappingEngine through out your code create an IObjectMapper interface. The interface I use contains method signatures taken directly out of automappers code.

public interface IObjectMapper
{ 
  TDestination Map(TSource source);
  TDestination Map(TSource source, TDestination destination);
  object Map(object source, Type sourceType, Type destinationType);
  object Map(object source, object destination, Type sourceType, Type destinationType);
}

Your configuration is still going to be automapper dependent.

A blog post I wrote on it is here: http://fodonnel.wordpress.com/2010/09/20/an-object-mapper-facade/

fodonnel