Подтвердить что ты не робот

Настройка встраивания зависимостей с помощью ASP.NET Web API 2.1

Я создаю сайт ASP.NET Web API 2.1, и поскольку я хочу встраивать зависимости непосредственно в контроллеры, я создал свою собственную реализацию IDependencyResolver, чтобы StructureMap обработал это для меня.

public class StructureMapDependencyResolver : IDependencyResolver
{
    public IDependencyScope BeginScope()
    {
        return this;
    }

    public object GetService(Type serviceType)
    {
        return ObjectFactory.GetInstance(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {            
        return ObjectFactory.GetAllInstances(serviceType).Cast<object>();
    }

    public void Dispose()
    {
    }
}

Затем я сказал Web API использовать этот класс, добавив эту строку в метод Application_Start в Global.asax

GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver();

Это скомпилировано, но когда я попытался получить доступ к любому из методов API в браузере, я получил ошибку, подобную этой

No Default Instance defined for PluginFamily System.Web.Http.Hosting.IHostBufferPolicySelector, System.Web.Http

Это было относительно легко решить, поскольку я добавил строку в конфигурацию StructureMap

this.For<IHostBufferPolicySelector>().Use<WebHostBufferPolicySelector>();

Однако затем я получил другие подобные ошибки для других классов System.Web.Http, и хотя я мог решить некоторые из них, я застрял в том, как иметь дело с тремя из них, а именно с ITraceManager, IExceptionHandler и IContentNegotiator.

Проблема заключается в том, что TraceManager, который по-видимому является реализацией ITraceManager по умолчанию, является внутренним классом, поэтому я не могу ссылаться на него в моей конфигурации StructureMap.

Итак, я об этом совершенно неправильно, или есть какой-то другой способ вставить эти внутренние классы?

4b9b3361

Ответ 1

Я хотел бы дать вам предложение и объяснение, почему бы не пойти этим путем и как сделать это по-другому (я бы сказал лучше и правильно).

Полное и полное объяснение несоответствующего дизайна IDependencyResolver можно найти здесь: Включение в зависимость и управление жизненным циклом с помощью веб-API ASP.NET Марк Семанн

Позвольте мне привести эти существенные части:

Проблема с IDependencyResolver

Основная проблема с IDependencyResolver заключается в том, что она по существу является локатором сервисов. Есть много проблем с Locator anti-pattern, но большинство из них я уже описал в другом месте этого блога (и в моей книге). Один из недостатков Service Locator, о котором я еще не писал, заключается в том, что в каждом вызове GetService нет никакого контекста. Это общая проблема с анти-шаблоном Service Locator, а не только с IDependencyResolver.

А также:

... граф зависимости должен знать что-то о контексте. Каков был URL-адрес запроса? Каков был базовый адрес (имя хоста и т.д.)? Как вы можете обмениваться экземплярами зависимостей в рамках одного запроса? Чтобы ответить на такие вопросы, вы должны знать об этом контексте, а IDependencyResolver не предоставляет эту информацию.

Короче говоря, IDependencyResolver не подходит для составления графиков зависимостей. ** К счастью, ASP.NET Web API имеет лучшую точку расширения для этой цели. **

ServiceActivator

Итак, ответом в этом случае будет ServiceActivator. Пожалуйста, взгляните на этот ответ:

Пример ServiceActivator:

public class ServiceActivator : IHttpControllerActivator
{
    public ServiceActivator(HttpConfiguration configuration) {}    

    public IHttpController Create(HttpRequestMessage request
        , HttpControllerDescriptor controllerDescriptor, Type controllerType)
    {
        var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
        return controller;
    }
}

Все, что мы можем сделать с StructureMap, на месте. Основные возможности платформы Web API все еще существуют... нам не нужно их взломать. И мы также скорее используем DI/IoC, затем локатор обслуживания

Ответ 2

Просто попробуйте использовать UnityHierarchicalDependencyResolver вместо другого. Это сработало для меня. Это для будущей ссылки, если кто-то захочет использовать Unity