Autofac, ASP.NET MVC 3 Область httpRequest и AutoMapper: область с тегом, совпадающим с httpRequest, не видна - PullRequest
2 голосов
/ 23 ноября 2011

Когда я использую веб-тип, зарегистрированный с помощью autofac из сопоставления autopper, я получаю эту ошибку:

Нет области с тегом, совпадающим с 'httpRequest', из области, в которой был экземплярпросил.Как правило, это указывает на то, что компонент, зарегистрированный как запрос на HTTP, запрашивается компонентом SingleInstance () (или аналогичным сценарием). При веб-интеграции всегда запрашивают зависимости из DependencyResolver.Current или ILifetimeScopeProvider.RequestLifetime, а не из самого контейнера.

Когда в отображении разрешается другой тип, он работает.Когда веб-тип разрешается из контроллера, он работает.

Почему веб-типы (или любые другие области действия httprequest?) Не могут быть успешно разрешены в моем отображении?

    protected void Application_Start()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule<AutofacWebTypesModule>();
        builder.RegisterControllers(Assembly.GetExecutingAssembly());
        builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
        builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
            .AssignableTo<Profile>()
            .As<Profile>()
            ;
        builder.Register(c => Mapper.Engine)
            .As<IMappingEngine>();
        builder.RegisterType<AnotherType>()
            .As<IAnotherType>();
        var container = builder.Build();

        DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

        var profiles = container.Resolve<IEnumerable<Profile>>();
        Mapper.Initialize(c => profiles.ToList().ForEach(c.AddProfile));

        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }

public class HomeController : Controller
{
    private readonly IMappingEngine _mapper;
    private readonly Func<HttpContextBase> _httpContext;

    public HomeController(IMappingEngine mapper, Func<HttpContextBase> httpContext)
    {
        _mapper = mapper;
        _httpContext = httpContext;
    }

    public ActionResult Index()
    {
        var test = _httpContext.Invoke();
        return View(_mapper.Map<Model, ViewModel>(new Model()));
    }

}

public class MyProfile : Profile
{
    private readonly Func<HttpContextBase> _httpContext;
    private readonly Func<IAnotherType> _anotherType;

    public MyProfile(Func<HttpContextBase> httpContext, Func<IAnotherType> anotherType)
    {
        _httpContext = httpContext;
        _anotherType = anotherType;
    }

    protected override void Configure()
    {
        CreateMap<Model, ViewModel>()
            .ForMember(d => d.Url, o => o.ResolveUsing(s =>
                                                    {
                                                        var test = _anotherType.Invoke().GetAValue();
                                                        return _httpContext.Invoke().Request.Url;
                                                    }))
            ;
    }
}

public interface IAnotherType
{
    string GetAValue();
}

public class AnotherType : IAnotherType
{
    public string GetAValue() { return "a value"; }
}

public class ViewModel
{
    public string Url { get; set; }
}

public class Model
{
}

РЕДАКТИРОВАТЬ: легко создать пустой проект MVC, вставить код, попробовать его и убедиться в этом.

EDIT : удален вызов ConstructServicesUsing, поскольку в примере это не требуется,В этом примере службы не разрешаются через AutoMapper.

Ответы [ 3 ]

2 голосов
/ 24 ноября 2011

@ rene_r выше находится на правильном пути; адаптируя свой ответ:

c.ConstructServicesUsing(t => DependencyResolver.Current.GetService(t))

Все еще может не скомпилироваться, но должно вас закрыть.

Требование состоит в том, что вызов DependencyResolver.Current откладывается до тех пор, пока не будет запрошен сервис (не сохраняется как значение, возвращаемое Current, когда инициализатор маппера).

0 голосов
/ 10 мая 2014

У меня недавно была похожая проблема, и это оказалось плохой настройкой в ​​моей функции начальной загрузки. Следующая настройка автофака сделала это для меня.

builder.Register(c => new ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers))
    .AsImplementedInterfaces()
    .SingleInstance();

builder.Register(c => Mapper.Engine)
    .As<IMappingEngine>()
    .SingleInstance();

builder.RegisterType<TypeMapFactory>()
    .As<ITypeMapFactory>()
    .SingleInstance();

Мне не нужно было указывать распознаватель в функции Mapper.Initialize (). Просто называется

Mapper.Initialize(x => 
            {
                x.AddProfile<DomainToDTOMappingProfile>(); 
            });

после начальной загрузки и у меня все работает нормально.

0 голосов
/ 23 ноября 2011

Я думаю, что вы должны использовать DependencyResolver.Current.Resolve вместо контейнера. Разрешить в

Mapper.Initialize(c =>
                {                               
                   c.ConstructServicesUsing(DependencyResolver.Current);
                   profiles.ToList().ForEach(c.AddProfile);
                 });
...