Я хочу настроить регистрацию в контейнере Unity, который используется ASP.NET Web API 2 на основе свойств HTTP-запроса. Например, запрос на /api/database1/values
должен привести к конфигурации контейнера Unity с параметром IDbContext
, настроенным для базы данных1, тогда как запрос /api/database4/values
получит IDbContext
, настроенный для базы данных4.Конфигурация контейнера Unity по запросу в промежуточном ПО OWIN
Я до сих пор использовал UnityHierarchicalDependencyResolver
в качестве преобразователя зависимостей, поэтому типы, зарегистрированные с HierarchicalLifetimeManager
, сохраняются только для срока службы запроса. Это хорошо работает для получения типов разрешено за запрос. Но как их получить зарегистрировано за запрос с использованием промежуточного программного обеспечения OWIN.
В моем промежуточном слое, вызов System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUnityContainer))
получает экземпляр IUnityContainer
, но это же контейнера для всех запросов, включая любые регистрации предыдущих запросов.
По инкапсуляции UnityHierarchicalDependencyResolver
с моей собственной реализацией IDependencyResolver
Я вижу, что IDependencyResolver.BeginScope
не вызывается до тех пор, пока в процессе не будет много. Таким образом, проблема заключается в том, что дочерний контейнер не создается до тех пор, пока веб-API не просыпается, после того, как мое промежуточное ПО вызовет Next(..)
.
Есть ли способ, с помощью которого я могу расширить сферу действия своего зависимого преобразователя, чтобы начать раньше? Есть ли какая-то другая стратегия, которую мне не хватает. В случае, если это имеет значение, я размещаю в IIS, но предпочитаю подход промежуточного программного обеспечения OWIN.
Update
Это не ответ, и это слишком большой для комментария, но после того, как изо всех сил, чтобы решить эту проблему с Unity я решил перейти на Autofac и все это просто встало на свои места.
Autofac Owin пакеты (Autofac.Mvc5.Owin
, Autofac.Owin
, Autofac.WebApi2.Owin
) делает его мертвым простой в использовании Autofac внутри трубопровода Owin и обеспечить надлежащее управление временем жизни в ASP.NET MVC и Web API. Это недостающее звено.
Я не мог найти способ перенастроить контейнер по запросу, но он по крайней мере позволил настроить фабрику по запросу (так что да, @Haukinger и @alltej, вы были правы, чтобы вставлять ., что направление
Так я зарегистрировать завод, как:
builder.RegisterType<DataDependencyFactory>().InstancePerRequest();
и зарегистрировать метод создания, что завод, как:
builder
.Register(c => c.Resolve<DataDependencyFactory>().CreateDataDependency())
.As<IDataDependency>()
.InstancePerRequest();
регистрируя завод этот путь особенно полезен, потому что нисходящие иждивенцы не должны знать о фабрике. Мне это нравится, потому что моим иждивенцам не нужна фабрика, им нужен экземпляр. Контейнер сгибается до потребностей моих иждивенцев, а не наоборот :)
Затем, в части промежуточного программного обеспечения OWIN, я разрешаю завод и устанавливаю свойство на нем в соответствии с свойствами запроса. Последующее разрешение IDataDependency
в контроллере MVC или Web API или что-то еще в конвейере OWIN получит экземпляр, настроенный в соответствии с свойством на заводе.
FWIW, я считаю, что я не пытаюсь сделать что-то действительно смешное, так как документация Autofac подтверждает эту концепцию. http://docs.autofac.org/en/latest/faq/per-request-scope.html#implementing-custom-per-request-semantics _ ** вы можете реализовать настраиваемый механизм, который обеспечивает возможность регистрации и разрешения зависимостей по каждому запросу **. Хотя я бы предпочел придерживаться Unity, если это тяжелая битва, я бы рассмотрел альтернативный контейнер IoC, такой как Autofac. – Snixtor
Считаете ли вы фабрику для вашего IDBContext, которая создает контекст и получает соответствующие свойства запроса в качестве параметра? Таким образом, вам нужна только одна регистрация для завода. – Haukinger
Завод по-прежнему нуждается в конфигурации для каждого запроса. Это означает, что ему нужно будет сразу узнать о соединении (не идеальном) или понадобится какой-то контекст соединения, который вводится через контейнер IoC, который возвращает меня обратно к квадрату. Или что-то мне не хватает? – Snixtor