public class ActionFilterVersionAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
if (actionContext.Request.Headers.Any(x => x.Key == "SetInternalVersion"))
{
// determine somehow that the **InternalSystem implementation** should be resolved when the controller class is instantiated with the **ISystem constructor** parameter
}
else
{
// determine somehow that the **ExternalSystem implementation** should be resolved when the controller class is instantiated with the **ISystem constructor** parameter
}
base.OnActionExecuting(actionContext);
}
}
Я имею ExternalSystem/InternalSystem with the ISystem interface.
Установите тип зарегистрированной службы во время выполнения в обработчик действия фильтра/сообщении
Как я могу сказать autofac впрыснуть ExternalSystem или InternalSystem в реализованным контроллер, как экземпляр ISystem в зависимости от строки значение, которое я передаю в ActionFilter или, возможно, обработчике сообщений.
Я знаю, что могу делать такие вещи, как:
builder.RegisterType<InternalSystem>().As<ISystem>().Keyed<ISystem>("Internal");
, где я могу использовать func<string,ISystem>
фабрику для решения класса во время выполнения, но это не то, что я хочу сделать.
На самом деле мне нужно зарегистрировать ISystem внутри фильтра действий, но тогда мне нужно каким-то образом передать контейнер в фильтр, но это не то, что я хочу ... и его тоже не возможно.
// Action: returns external or internal value
public string Get()
{
return resolvedISystem.Get();
}
Конечно, я мог бы разрешить ISystem в зависимости от Func завода в пределах каждого одиночного действия или положить поведение в базовый контроллер, где я проверяю для заголовка, но я действительно предпочел бы действие фильтра, как это может быть просто глобально зарегистрировано ОДИН раз, но для каждого нового контроллера я должен подклассифицировать базовый контроллер.
Базовый образец контроллер с псевдо-кодом, потому что base.Request является нулевым, который нуждается в другой обходной путь/исправить ...
public class BaseController : ApiController
{
public BaseController(Func<string, ISystem> dataServiceFactory)
{
string system = base.Request.Headers.Any(x => x.Key == "SetInternalVersion") ? "internal" : "external";
System = dataServiceFactory(system);
}
public ISystem System { get; set; }
}
ОБНОВЛЕНИЕ контейнер также отмечен как OBSOLETE автором Autofac.
Таким образом, я не хочу добавлять регистрацию в свой фильтр/обработчик и обновлять/строить контейнер снова.
1.) Я пытался теперь обработчик сообщений обновляют контейнер, который работает, но это не должно быть сделано из-за устаревшее предупреждение. 2.) Я попробовал фабрику func в фильтре действий, добавляя разрешенную услугу к request.Properties bag 3.) Если ваше решение работает, технически это самое сложное, я не знал о регистрации текущего запроса, который действительно хорошенькая идея! – Pascal
Отлично работает. Я по-прежнему поддерживаю этот ответ как хороший! Спасибо. – Pascal
Хотя ответ верный, факт, что вы полагаетесь на «HttpContext.Current», немного шелушится, как если бы вы использовали Web API поверх OWIN, «HttpContext.Current» не установлен. Я бы предложил использовать метод расширения RegisterHttpRequestMessage' в 'ContainerBuilder'. Это регистрирует «HttpRequestMessage» с областью действия запроса на HTTP. Затем 'SystemKeyProvider' мог использовать его вместо' HttpContext'. –