2012-07-24 88 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