2011-07-08 63 views
4

我想使用this文章的方法,但我错过了一些东西 - 我目前在WindsorControllerFactory.GetControllerInstance中出现错误,因为WindsorActionInvoker对IWindsorContainer有依赖关系时它会尝试解析IActionInvoker 。Castle Windsor - 注入IActionInvoker实现问题

鉴于WindsorControllerFactory已经有了对IWindsorContainer的引用,我可以在那里传递该引用吗?如果是这样 - 如何?我发现的唯一例子是关于传递值类型作为构造函数参数,而不是引用类型。

我感觉我失去了一些东西明显...

当前设置如下: 在Global.asax中的Application_Start我叫下面的方法:

protected virtual IWindsorContainer InitializeServiceLocator() 
    { 
     IWindsorContainer container = new WindsorContainer(); 
     ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container)); 

     container.RegisterControllers(typeof(HomeController).Assembly); 
     ComponentRegistrar.AddComponentsTo(container); 

     return container; 
    } 

ComponentRegistrar:

public static void AddComponentsTo(IWindsorContainer container) 
{ 
     //add other components..... 

     container.AddComponentLifeStyle<IActionInvoker, WindsorActionInvoker>(LifestyleType.PerWebRequest); 

} 

WindsorActionInvoker:

public class WindsorActionInvoker : ControllerActionInvoker, IActionInvoker 
{ 
    readonly IWindsorContainer container; 

    public WindsorActionInvoker(IWindsorContainer container) 
    { 
     this.container = container; 
    } 

    protected override ActionExecutedContext InvokeActionMethodWithFilters(
      ControllerContext controllerContext, 
      IList<IActionFilter> filters, 
      ActionDescriptor actionDescriptor, 
      IDictionary<string, object> parameters) 
    { 
     foreach (IActionFilter actionFilter in filters) 
     { 
      container.Kernel.InjectProperties(actionFilter); 
     } 
     return base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); 
    } 
} 

WindsorControllerFactory:

public class WindsorControllerFactory : DefaultControllerFactory 
{ 
    private readonly IWindsorContainer container; 

    public WindsorControllerFactory(IWindsorContainer container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException("container"); 
     } 
     this.container = container; 
    } 

    public override void ReleaseController(IController controller) 
    { 
     var disposable = controller as IDisposable; 

     if (disposable != null) 
     { 
      disposable.Dispose(); 
     } 

     this.container.Release(controller); 
    } 

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      return base.GetControllerInstance(requestContext, controllerType); 
     } 

     var controller = this.container.Resolve(controllerType) as Controller; 

     if (controller != null) 
     { 
      controller.ActionInvoker = this.container.Resolve<IActionInvoker>(this.container); 
     } 

     return controller; 
    } 
} 

更新

我错过了一个细微之处:我试图用这种行为为以下:

public class CustomAuthorize : AuthorizeAttribute {...} 

不执行IActionFilter

增加了以下内容WindsorActionInvoker:

protected override AuthorizationContext InvokeAuthorizationFilters(ControllerContext controllerContext, IList<IAuthorizationFilter> filters, ActionDescriptor actionDescriptor) 
    { 
     foreach (IAuthorizationFilter authorizeFilter in filters) 
     { 
      this.kernel.InjectProperties(authorizeFilter); 
     } 
     return base.InvokeAuthorizationFilters(controllerContext, filters, actionDescriptor); 
    } 

要求这现在工作。感谢Cristiano,因为它分析了他亲切的代码,使我走上了正确的道路。

回答

8

的Global.asax

private static void bootstrapContainer() 
{ 
    container = new WindsorContainer() 
     .Install(FromAssembly.This()); 
    var controllerFactory = new WindsorControllerFactory(container.Kernel); 

    ControllerBuilder.Current.SetControllerFactory(controllerFactory); 
} 

安装人员/灌装容器

public class ControllersInstaller : IWindsorInstaller 
{ 
    #region IWindsorInstaller Members 

    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Component.For<WpRegistration.Web.Filters.AgencyAuthorize>().LifeStyle.Transient); 
     container.Register(Component.For<IActionInvoker>().ImplementedBy<WindsorExtensions.Mvc.WindsorActionInvoker>().LifeStyle.Transient); 

     container.Register(AllTypes.FromThisAssembly() 
          .BasedOn<IController>() 
          .If(Component.IsInSameNamespaceAs<HomeController>()) 
          .If(t => t.Name.EndsWith("Controller")) 
          .Configure((c => c.LifeStyle.Transient))); 
    } 

    #endregion 
} 

WindsorControllerFactory

using System; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Routing; 

using Castle.MicroKernel; 

public class WindsorControllerFactory : DefaultControllerFactory 
{ 
    private readonly IKernel kernel; 

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

    public override void ReleaseController(IController controller) 
    { 
     kernel.ReleaseComponent(controller); 
    } 

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path)); 
     } 

    IController iController = (IController)kernel.Resolve(controllerType); 

    // new code  
    if (iController is Controller)  
    { 
     ((Controller)iController).ActionInvoker = kernel.Resolve<IActionInvoker>(); 
    } 

    return iController; 
    } 
} 

WindsorActionInvoker

namespace WindsorExtensions.Mvc 
{ 

    public class WindsorActionInvoker : ControllerActionInvoker 
    { 
     readonly IKernel kernel; 
     public WindsorActionInvoker(IKernel kernel) 
     { 
      this.kernel = kernel; 
     } 
     protected override ActionExecutedContext InvokeActionMethodWithFilters(
      ControllerContext controllerContext 
      , IList<IActionFilter> filters 
      , ActionDescriptor actionDescriptor 
      , IDictionary<string, object> parameters) 
     { 
      foreach (IActionFilter actionFilter in filters) 
      { 
       kernel.InjectProperties(actionFilter); 
      } 
      return base.InvokeActionMethodWithFilters(controllerContext, filters, actionDescriptor, parameters); 
     } 
    } 

    public static class WindsorExtension 
    { 
     public static void InjectProperties(this IKernel kernel, object target) 
     { 
      var type = target.GetType(); 
      foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) 
      { 
       if (property.CanWrite && kernel.HasComponent(property.PropertyType)) 
       { 
        var value = kernel.Resolve(property.PropertyType); 
        try { property.SetValue(target, value, null); } 
        catch (Exception ex) 
        { 
         var message = string.Format("Error setting property {0} on type {1}, See inner exception for more information.", property.Name, type.FullName); 
         throw new ComponentActivatorException(message, ex); 
        } 
       } 
      } 
     } 
    } 
} 

AgencyAuthorizeAttribute

namespace WpRegistration.Web.Filters 
{ 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 
    public sealed class AgencyAuthorize : ActionFilterAttribute 
    { 
     CurrentUserService _currentUserSvc; 
     public AgencyAuthorize() { } 

     public CurrentUserService Service 
     { 
      get { return _currentUserSvc; } 
      set 
      { 
       this._currentUserSvc=value; 
      } 
     } 
+0

感谢 - 这让我有点进一步 - 然而InvokeActionMethodWithFilters没有得到执行,所以我的财产的依赖性永远不会被注入。 – BonyT

+0

我编辑完整的实施我的答案。它适用于我很好 – Crixo

+0

非常感谢您的亲切努力 - 我会试试这个。 – BonyT