0

我有一個具有多個圖層(組件)的項目。我用Castle Windsor來解決依賴注入。也用城堡創建我的控制器。所以我在Web API和WebUI Layers中安裝並使用了Castle。除了我有一個引導程序層,它註冊了所有服務和存儲庫。WindsorControllerActivator中的ArgumentNullException

首先我的Web API:

在WebApiConfig.cs文件,我註冊了UI的依賴與流動代碼:

public static void Register(HttpConfiguration config) 
    { 

     var corsAttr = new EnableCorsAttribute("*", "*", "*"); 
     config.EnableCors(corsAttr); 

     // Web API configuration and services 
     var container = Bootstrapper.WireUp();// to register services and repositories 
     RegisterControllers(container); 
     config.Services.Replace(typeof(IHttpControllerActivator), new WindsorControllerActivator(container)); 

    } 

    private static void RegisterControllers(IWindsorContainer container) 
    { 
     //container.Register(Component.For<VisitorController>().LifestylePerWebRequest()); 
     //container.Register(Component.For<ValueController>().LifestylePerWebRequest()); 
     //container.Register(Component.For<ValidateController>().LifestylePerWebRequest()); 
     //container.Register(Component.For<CaptchaImageController>().LifestylePerWebRequest()); 
     container.Register(Classes.FromAssemblyContaining<VisitorController>() 
      .BasedOn<ApiController>().LifestyleTransient()); 
    } 

和催化劑廠是這樣的:

public class WindsorControllerActivator : IHttpControllerActivator 
{ 
    private readonly IWindsorContainer _container; 
    public WindsorControllerActivator(IWindsorContainer container) 
    { 
     _container = container; 
    } 

    public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) 
    { 
     return (IHttpController)_container.Resolve(controllerType);//System.ArgumentNullException: Value cannot be null. error 
    } 
} 

同樣在WebUI項目中,我使用Castle Windsor來創建我的控制器。但是,當我運行該項目,我得到「System.ArgumentNullException:值不能爲空。」錯誤時解決Controller.I在這一行的意思是:

(IHttpController)_container.Resolve(controllerType); 

我也試過「LifeStylePerWebRequest」我的控制器和沒有什麼改變。

還有什麼,WireUp方法沒有問題,(註冊服務和存儲庫工作正常)。這個問題僅適用於控制器(在WebUI和WebApi項目中)。 WebUI項目也會出現同樣的問題。

+0

顯示異常的堆棧跟蹤。 – Fran

+0

當您在Create方法中放置斷點時,您可以檢查已註冊的依賴關係。 controllerType是其中之一嗎?另外作爲一個便箋,如果您使用瞬態生活方式,不要忘記釋放控制器。你可以看看這篇文章http://blog.ploeh.dk/2012/10/03/DependencyInjectioninASP.NETWebAPIwithCastleWindsor/ – RVid

+0

我在WebUI中使用了LifestylePerWebRequest,並且我得到了同樣的錯誤。 – Afsaneh

回答

1

我通常使用IDependencyResolver而不是IHttpControllerActivator的實現。您可以改爲這種方法。添加floowing類:

public class WindsorDependencyResolver : IDependencyResolver 
{ 
    readonly IWindsorContainer _container; 

    public WindsorDependencyResolver(IWindsorContainer container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException(nameof(container)); 
     } 

     _container = container; 
    } 

    public IDependencyScope BeginScope() 
    { 
     return new WindsorDependencyScope(this, _container.Release); 
    } 

    public void Dispose() 
    { 
    } 

    public object GetService(Type t) 
    { 
     var ret = _container.Kernel.HasComponent(t) ? _container.Resolve(t) : null; 
     return ret; 
    } 

    public IEnumerable<object> GetServices(Type t) 
    { 
     var ret = _container.ResolveAll(t).Cast<object>().ToArray(); 
     return ret; 
    } 
} 

這個類是由依賴解析器要求:

public class WindsorDependencyScope : IDependencyScope 
    { 
     readonly List<object> _instances; 
     readonly Action<object> _release; 
     readonly IDependencyScope _scope; 

     public WindsorDependencyScope(IDependencyScope scope, Action<object> release) 
     { 
      if (scope == null) 
      { 
       throw new ArgumentNullException(nameof(scope)); 
      } 

      if (release == null) 
      { 
       throw new ArgumentNullException(nameof(release)); 
      } 

      _scope = scope; 
      _release = release; 
      _instances = new List<object>(); 
     } 

     public void Dispose() 
     { 
      foreach (object instance in _instances) 
      { 
       _release(instance); 
      } 

      _instances.Clear(); 
     } 

     public object GetService(Type t) 
     { 
      var service = _scope.GetService(t); 
      AddToScope(service); 

      return service; 
     } 

     public IEnumerable<object> GetServices(Type t) 
     { 
      var services = _scope.GetServices(t); 
      AddToScope(services); 

      return services; 
     } 

     void AddToScope(params object[] services) 
     { 
      if (services.Any()) 
      { 
       _instances.AddRange(services); 
      } 
     } 
    } 

這就是你如何在註冊的依賴解析器你Register方法:

config.DependencyResolver = new WindsorDependencyResolver(container); 

我建議在註冊您的控制器時使用生活方式瞬態,因爲依賴關係解析器負責處理它們。

+0

仍然會發生同樣的錯誤。我不知道服務器有什麼問題。 – Afsaneh

+0

我使用DI爲WebApi層和WebUI層。但我用不同的組件測試來創建容器。每個容器分別註冊服務和存儲庫。我不應該爲所有圖層使用相同的容器嗎? – Afsaneh

+0

您應該只有一個應用程序實例的容器。通過Web UI,你的意思是ASP.net MVC?我不確定您的解決方案是如何構建的,但是您的API控制器與MVC控制器在相同的應用程序實例中? (即如果您使用的是MVC) – RVid