2016-03-23 7 views
1

Я использую DryIOC.WebAPI для решения своих APICконтроллеров.Резервный контроллер DryIOC WebAPI

WebAPI Config таким образом:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     // Web API configuration and services 
     // Configure Web API to use only bearer token authentication. 
     config.SuppressDefaultHostAuthentication(); 
     config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType)); 


     config.EnableCors(); 
     config.MapHttpAttributeRoutes(); 

     config.Routes.MapHttpRoute(
      name: "DefaultApi", 
      routeTemplate: "api/{controller}/{id}", 
      defaults: new { id = RouteParameter.Optional } 
     ); 

     Startup.IocContainer.WithWebApi(config); 
     Startup.IocContainer.RegisterWebApiControllers(config); 
    } 
} 

Его работает прекрасно, пока я не забудьте создать отображение в контейнер МОК. В этом случае преобразователь зависимостей не сможет создать экземпляр APIController с использованием DryIOC.

Когда это происходит, оно возвращается к стандартным преобразователям WebAPI, которые затем запираются с ошибкой «Нет конструктора по умолчанию».

Это нежелательное поведение для меня. Если разрешение DryIOC выходит из строя, я хочу, чтобы все прекратилось там - не было возврата к реализации по умолчанию, и не было неточное сообщение об отсутствии конструктора по умолчанию. Я хочу знать, какие типы DryIOC не могут решить, поэтому я могу это исправить.

Как я могу это достичь?

+0

вы можете переопределить распознаватель по умолчанию самостоятельно, прежде чем передавать его в DryIOC и остановить его – Nkosi

+0

Я сделал запрос DryIOC Pull: https://bitbucket.org/dadhi/dryioc/pull-requests/15/changed-the- разрешение-поведение-to-throw/diff – reach4thelasers

+0

, что делает изменения в структуре DryIOC довольно экстремальными. Вы должны воспользоваться возможностью расширения, которую позволяет веб-api. Посмотрев, как источник DryIOC заменяет средство распознавания по умолчанию, а не завершает его, я отредактирую свой ответ, чтобы показать, как вы могли бы обернуть DryIOCResover и выбросить ошибку, которую вы хотите. – Nkosi

ответ

1

Согласно документации Microsoft:

Dependency Injection in ASP.NET Web API 2

Если GetService метод не может разрешить тип, он должен вернуть нуль. Если метод GetServices не может решить тип, он должен вернуть пустой объект коллекции.

Не бросайте исключения для неизвестных типов.

Реализации этого интерфейса должны делегировать базовому контейнеру для инъекций , чтобы предоставить зарегистрированную услугу для запрашиваемого типа. Когда нет зарегистрированных услуг запрашиваемого типа, рамки ASP.NET MVC ожидает реализация этого интерфейс, чтобы вернуть нуль из GetService и вернуть пустую коллекции из GetServices.

Когда Web API создает экземпляр контроллера, он сначала вызывает IDependencyResolver.GetService, передавая тип контроллера. Вы можете использовать этот крючок расширяемости для создания контроллера, , разрешающего любые зависимости. Если GetService возвращает null, Web API выглядит для конструктора без параметров в классе контроллера.

Вы можете изменить настройки по умолчанию решающего себя

public static class ResolverHelper { 
    public static void OverrideResolver(this HttpConfiguration httpConfiguration) { 
     var innerResolver = httpConfiguration.DependencyResolver; 
     var resolver = new MyDryIocDependencyResolver(innerResolver); 
     httpConfiguration.DependencyResolver = resolver; 
    } 
} 

и в пользовательском распознавателе неудачи, как вы хотите.

Отрывок из MyDryIocDependencyResolver

public class MyDryIocDependencyResolver : IDependencyResolver { 
    IDependencyResolver innerResolver; 

    public MyCustomDependencyResolver(IDependencyResolver innerResolver) { 
     this.innerResolver = innerResolver; 
    } 

    public IDependencyScope BeginScope() { 
     return this; 
    } 

    public object GetService(Type serviceType) { 
     try { 
      return innerResolver.Getservice(serviceType); 
     } catch (Exception ex) { 
      //TODO: Log resolution error 
      return null; 
     } 
    } 

    public IEnumerable<object> GetServices(Type serviceType) { 
     try { 
      return innerResolver.GetServices(serviceType); 
     } catch (Exception ex) { 
      //TODO: Log resolution error 
      return new List<object>(); 
     } 
    } 

    public void Dispose() { 
     // NO-OP 
    } 
} 

В вашей регистрации вы можете переопределить его

//...other code 
Startup.IocContainer.WithWebApi(config); 
Startup.IocContainer.RegisterWebApiControllers(config); 
config.OverrideResolver(); 
//...other code 

Таким образом, если/когда DryIocDependencyResolver не может разрешить тип сервиса вы еще знаете, что не был решен, уловить его и вернуть значения по умолчанию, как указано в предлагаемых рекомендациях. Лучшее обоих миров.

Надежда, что помогает

+1

Это действительно рекомендация MS. Проблема в том, что мы теряем подробное исключение из интегрированной библиотеки IoC. DryIoc и другие IoCs предоставляют много информации о том, что, почему не разрешено, и каково состояние контейнера. Таким образом, вы можете определить проблему намного быстрее. – dadhi

1

Другой способ проверить проблемы с разрешением контроллера со всей возможной информации, чтобы использовать IContainer.VerifyResolutions метод.

Например:

var container = new Container().WithWebApi(config); 
var errors = container.VerifyResolutions(); 
Debug.Assert(errors.Length == 0); 

Подробнее в wiki.

Примечание: Единственная загвоздка с контроллерами, что ток DryIoc.WebApi регистров реализация контроллера с конкретным типом контроллера и все его реализованными типами как типы услуг. Таким образом, для одного нерешенного class MyController: ApiController {} метода VerifyResolutions будет возвращать 3 одинаковых ошибки:

  • один для MyController
  • один для ApiController
  • и один для IHttpController

Вы можете группы результат проверки errors по Factory.FactoryID в имеют более компактный выход.

Смежные вопросы