温莎城堡-注入IActionInvoker实现问题

本文关键字:IActionInvoker 实现 问题 注入 城堡 | 更新日期: 2023-09-27 18:01:27

我正试图使用本文中的方法,但我错过了一些东西-我目前在WindsorControllerFactory中得到一个错误。

当它试图解析IActionInvoker时,GetControllerInstance .

考虑到WindsorControllerFactory已经有一个对IWindsorContainer的引用,我可以传递那个引用吗?如果有,怎么做?我找到的唯一的例子是关于传递值类型作为构造函数参数,而不是引用类型。

我觉得我错过了一些明显的东西…

当前设置如下:在全球。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);
    }

现在可以按要求工作了。感谢克里斯蒂亚诺,因为这是对他好心提供的代码的分析,使我走上了正确的道路。

温莎城堡-注入IActionInvoker实现问题

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;
            }
        }