2012-07-24 89 views
2

我正在看看ASP.NET MVC 4 RC,並且找不到DefaultHttpControllerFactory,甚至找不到IHttpControllerFactory來允許我選擇的IoC容器(Castle Windsor)掛鉤到Web Api框架中控制器。我最終使用了IDependencyResolver,這使得發佈組件變得有點棘手,但最終以下列結果。在IDependencyResolver有一個Release方法之前它會工作/不是內存泄漏嗎? Global.asax中結束爲:ASP.NET MVC 4 RC與Castle Windsor

public class WebApiApplication : System.Web.HttpApplication 
{ 
    private IWindsorContainer container; 

    protected void Application_Start() 
    { 
     AreaRegistration.RegisterAllAreas(); 

     FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
     RouteConfig.RegisterRoutes(RouteTable.Routes); 
     BundleConfig.RegisterBundles(BundleTable.Bundles); 

     Windsor(); 
    } 

    protected void Application_End() 
    { 
     container.Dispose(); 
    } 

    private void Windsor() 
    { 
     container = new WindsorContainer().Install(FromAssembly.This()); 

     // mvc: 
     var mvcControllerFactory = new WindsorControllerFactory(container.Kernel); 
     ControllerBuilder.Current.SetControllerFactory(mvcControllerFactory); 

     // web api: 
     var httpDependencyResolver = new WindsorHttpDependencyResolver(container.Kernel); 
     GlobalConfiguration.Configuration.DependencyResolver = httpDependencyResolver; 
    } 
} 

WindsorControllerFactory是DefaultControllerFactory的擴展MVC控制器並有溫莎安裝它們。 WindsorHttpDependencyResolver結束爲:

public class WindsorHttpDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver 
{ 
    private readonly IKernel kernel; 

    public WindsorHttpDependencyResolver(IKernel kernel) 
    { 
     this.kernel = kernel; 
    } 

    public IDependencyScope BeginScope() 
    { 
     return kernel.Resolve<IDependencyScope>(); // instances released suitably (at end of web request) 
    } 

    public object GetService(Type serviceType) 
    { 
     // for ModelMetadataProvider and other MVC related types that may have been added to the container 
     // check the lifecycle of these registrations 
     return kernel.HasComponent(serviceType) ? kernel.Resolve(serviceType) : null; 
    } 

    public IEnumerable<object> GetServices(Type serviceType) 
    { 
     return kernel.HasComponent(serviceType) ? kernel.ResolveAll(serviceType) as IEnumerable<object> : Enumerable.Empty<object>(); 
    } 

    public void Dispose() 
    { 
     // Nothing created so nothing to dispose - kernel will take care of its own 
    } 
} 

從理論上講,這意味着現在溫莎將提供API的控制器,一旦被安裝:

public class ApiControllersInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.AddFacility<TypedFactoryFacility>(); 
     container.Register(Component.For<ITypedFactoryComponentSelector>().ImplementedBy<WebApiTypedFactoryComponentSelector>()); 
     container.Register(Component.For<IDependencyScope>().AsFactory(tfc => tfc.SelectedWith<WebApiTypedFactoryComponentSelector>()).LifestylePerWebRequest()); 

     container.Register(Classes.FromAssemblyContaining<ValuesController>().BasedOn<IHttpController>().LifestyleTransient()); 
    } 
} 

我使用的是類型化的工廠設施,以實現IDependencyScope我,這意味着當框架在請求的末尾處理它時,它將隱含地釋放控制器及其依賴關係。通過使用Per Web Request生命週期,Windsor也將釋放工廠本身。這只是葉自定義類型工廠組件選擇作爲GetService的(一個或多個)容器不會找到任何東西:

public class WebApiTypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector 
{ 
    protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments) 
    { 
     if (method.Name == "GetService" || method.Name == "GetServices") 
     { 
      return (arguments[0] as Type).FullName; 
     } 
     return base.GetComponentName(method, arguments); 
    } 

    protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments) 
    { 
     if (method.Name == "GetService" || method.Name == "GetServices") 
     { 
      return arguments[0] as Type; 
     } 
     return base.GetComponentType(method, arguments); 
    } 
} 

希望這是非常有用的。

+0

是你的問題「它是否會工作/內存泄漏,直到IDependencyResolver有一個發佈方法?」? – 2012-07-24 21:41:47

+0

@Jesse我想我試圖找出這是否是一個可行的方法給予MVC 4 RC的結構。我想我已經正確理解了Windsor文檔,但是如果我在某處犯了錯誤,如果有人指出它會很感激。 – hagrid27 2012-07-24 22:00:35

回答

3

我最終使用了this blog post(Mark Seemann的this other one進一步增強了)的代碼,它爲每個請求創建一個範圍,並負責釋放創建的對象。這與你所採用的方法略有不同。

+0

感謝您的鏈接,看起來很有趣。 – hagrid27 2012-08-10 21:59:05