1

I'm throwing together some code for an internal demo which consists of a Silverlight 5.0 UI built on Caliburn.Micro.

Summary Scenario: I'm attempting to get AutoMapper to map a list of view models from a service proxy class. The view models have a ctor dependancy so I want to use Ninject to resolve this.

Details: I have a parent view model (AvailableItemsViewModel) which makes a call to a service. It then maps the list of DTO's returned to AvailableItemViewModel using AutoMapper.

The AvailableItemViewModel takes a reference to Caliburn's IEventAggregator - as the view model will publish an event based on user input.

I've read:

Injecting AutoMapper dependencies using Ninject

AutoMapper with Ninject confusion

How to configure Automapper to be injected with Ninject 2.0?

All of which seem fairly similar... so i've ended up with the following in my Bootstrap class:

 public class AutoMapperModule : NinjectModule
    {
        public override void Load()
        {
            Bind<ITypeMapFactory>().To<TypeMapFactory>();

            foreach (var mapper in MapperRegistry.AllMappers())
                Bind<IObjectMapper>().ToConstant(mapper);

            Bind<ConfigurationStore>().ToSelf().InSingletonScope().WithConstructorArgument("mappers", ctx => ctx.Kernel.GetAll<IObjectMapper>());
            Bind<IConfiguration>().ToMethod(ctx => ctx.Kernel.Get<ConfigurationStore>());
            Bind<IConfigurationProvider>().ToMethod(ctx => ctx.Kernel.Get<ConfigurationStore>());
            Bind<IMappingEngine>().To<MappingEngine>();

            Mapper.Initialize(cfg =>
            {
                cfg.ConstructServicesUsing(t=>Kernel.Get(t));                
            });

        }
    }

If i set a breakpoint in the bootstrapper, i see that Ninject can successfully create an instance of the AvailableItemViewModel.

Error is:

{System.ArgumentException: Type 'Caliburn.Proto.ViewModels.AvailableItemViewModel' does not have a default constructor at System.Linq.Expressions.Expression.New(Type type) at AutoMapper.DelegateFactory.<>c__DisplayClass1.b__0(Type t) at TvdP.Collections.ConcurrentDictionary2.GetOrAdd(TKey key, Func2 valueFactory) at AutoMapper.DelegateFactory.CreateCtor(Type type) at AutoMapper.Mappers.ObjectCreator.CreateObject(Type type) at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.CreateObject(ResolutionContext context) at AutoMapper.Mappers.TypeMapObjectMapperRegistry.NewObjectPropertyMapMappingStrategy.GetMappedObject(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper) at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)}

So Ninject is not being used?

Code to do the mapping is:

var availItems = Mapper.Map<List<Item>, List<AvailableItemViewModel>>(shoppingListStore.GetAvailableItems().ToList());

AvailableItems = new ObservableCollection<AvailableItemViewModel>(availItems);

What am i missing?

(AutoMapper is ver 2.1.267.0, Ninject is 3.0.0.0. I'm also using Ninject.Conventions)

[Update] I note that the "workaround" in the post AutoMapper with Ninject also works for me.

[Update] Given this: Mapper.CreateMap().ConstructUsingServiceLocator();

If i remove the ConstructUsingServiceLocator() method then the breakpoint on Kernel.Get:

cfg.ConstructServicesUsing(t=>Kernel.Get(t));

does not trigger. So it appears both are required?

Community
  • 1
  • 1
6footunder
  • 1,318
  • 18
  • 29

0 Answers0