温莎城堡-注入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);
}
现在可以按要求工作了。感谢克里斯蒂亚诺,因为这是对他好心提供的代码的分析,使我走上了正确的道路。
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;
}
}