Как заставить Unity передать параметр конструктора на основе запроса веб-API?

Я использую Web API в многопользовательской среде. У каждого арендатора своя база данных с идентичной структурой. Имя арендатора включено в URL-адрес как поддомен: http://{tenant}.mysite.com/api/doodad/action.

Я написал фильтр сообщений (DelegatingHandler), чтобы получить имя арендатора и найти соответствующую базу данных. В настоящее время я прячу это значение в параметрах запроса.

Практически каждое действие контроллера требует доступа к DbContext, указывающему на эту базу данных. Я не использую шаблон репозитория. Я создал второй конструктор в моем DbContext, который принимает имя базы данных.

Я использую Unity для внедрения экземпляра DbContext в ApiController. Как я могу заставить Unity вызывать второй конструктор для DbContext, передавая значение из параметра запроса?


person Patrick J Collins    schedule 19.05.2014    source источник
comment
Используйте факторный метод регистрации. Таким образом, именно вы предоставляете явный фабричный метод.   -  person Wiktor Zychla    schedule 19.05.2014


Ответы (1)


Я еще не пробовал это, но я думаю, что это должно сработать...

Вы можете создать фильтр действий, который добавит HttpRequestMessage в текущий иерархический контейнер, а затем зарегистрируете свой собственный тип DbContext с помощью InjectionFactory, чтобы извлечь HttpRequestMessage и получить имя БД.

Вот непроверенный код...

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class RegisterHttpRequestActionAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var container = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUnityContainer)) as IUnityContainer;
        container.RegisterInstance(actionContext.Request, new HierarchicalLifetimeManager());
    }
}

а конфигурация...

IUnityContainer rootContainer = new UnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new UnityHierarchicalDependencyResolver(rootContainer);
GlobalConfiguration.Configuration.Filters.Add(new RegisterHttpRequestActionAttribute());

rootContainer.RegisterType<MyDbContext>(new HierarchicalLifetimeManager(), new InjectionFactory(container => 
    new MyDbContext(container.Resolve<HttpRequestMessage>().Properties["TenantDB"] as string)));

(К вашему сведению, я ссылаюсь на пакет Unity.AspNet.WebApi NuGet, чтобы получить UnityHierarchicalDependencyResolver)

person TylerOhlsen    schedule 22.05.2014