Как использовать AutoMapper с Ninject.Сеть.В MVC?

настройка

у меня есть AutoMapperConfiguration статический класс, который устанавливает сопоставления AutoMapper:

static class AutoMapperConfiguration()
{
    internal static void SetupMappings()
    {
        Mapper.CreateMap<long, Category>.ConvertUsing<IdToEntityConverter<Category>>();
    }
}

здесь IdToEntityConverter<T> обычай ITypeConverter это выглядит так:

class IdToEntityConverter<T> : ITypeConverter<long, T> where T : Entity
{
    private readonly IRepository _repo;

    public IdToEntityConverter(IRepository repo)
    {
        _repo = repo;
    }

    public T Convert(ResolutionContext context)
    {
        return _repo.GetSingle<T>(context.SourceValue);
    }
}

IdToEntityConverter принимает IRepository в своем конструкторе, чтобы преобразовать идентификатор обратно в фактический объект, нажав на базу данных. Обратите внимание, что у него нет конструктора по умолчанию.

в моем ASP.NET s Global.asax, это то, что у меня есть для OnApplicationStarted() и CreateKernel():

protected override void OnApplicationStarted()
{
    // stuff that's required by MVC
    AreaRegistration.RegisterAllAreas();
    RegisterRoutes(RouteTable.Routes);

    // our setup stuff
    AutoMapperConfiguration.SetupMappings();
}

protected override IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Bind<IRepository>().To<NHibRepository>();

    return kernel;
}

так OnApplicationCreated() будем называть AutoMapperConfiguration.SetupMappings() настройки отображения и CreateKernel() свяжет экземпляр NHibRepository до .

всякий раз, когда я запускаю этот код и пытаюсь заставить AutoMapper преобразовать идентификатор категории обратно в объект категории, я получаю AutoMapperMappingException это говорит, что конструктор по умолчанию не существует на IdToEntityConverter.

попытки

  1. добавлен конструктор по умолчанию IdToEntityConverter. Теперь я получаю NullReferenceException, что указывает на то, что инъекция не работает.

  2. сделал отдельный _repo поле в публичное свойство и добавил . Все еще получаю NullReferenceException.

  3. добавил [Inject] атрибут конструктора, который принимает IRepository. Все еще получаю NullReferenceException.

  4. думая, что, возможно, Ninject не может перехватить AutoMapperConfiguration.SetupMappings() вызов в OnApplicationStarted(), я переехал это к чему-то, что я знаю, впрыскивает правильно, один из моих контроллеров, например:

    public class RepositoryController : Controller
    {
        static RepositoryController()
        {
            AutoMapperConfiguration.SetupMappings();
        }
    }
    

    все еще получаю NullReferenceException.

вопрос

мой вопрос в том, как заставить Ninject ввести IRepository на IdToEntityConverter?

2 ответов


вы должны предоставить AutoMapper доступ к контейнеру DI. Мы используем StructureMap, но я думаю, что ниже должно работать с любым DI.

мы используем это (в одной из наших задач загрузчика)...

    private IContainer _container; //Structuremap container

    Mapper.Initialize(map =>
    {
        map.ConstructServicesUsing(_container.GetInstance);
        map.AddProfile<MyMapperProfile>();
    }

ответ@ozczecho является точечным, но я публикую версию Ninject кода, потому что у него есть одно небольшое предостережение, которое поймало нас на некоторое время:

IKernel kernel = null; // Make sure your kernel is initialized here

Mapper.Initialize(map =>
{
    map.ConstructServicesUsing(t => kernel.Get(t));
});

вы не можете просто пройти в kernel.Get to map.ConstructServicesUsing потому что этот способ имеет params параметр в дополнение к типу. Но поскольку параметры являются необязательными, вы можете просто создать лямбда-выражение, чтобы создать анонимную функцию, чтобы получить то, что вам нужно.