温莎城堡 - 注射IActionInvoker执行问题 [英] Castle Windsor - Injecting IActionInvoker Implementation Issue
问题描述
我想使用的方法从的这个文章,但我失去了一些东西 - 我目前得到,当它试图解决IActionInvoker因为WindsorActionInvoker内WindsorControllerFactory.GetControllerInstance错误对IWindsorContainer依赖
由于WindsorControllerFactory已经具备IWindsorContainer一个参考,我能通过在参考?如果是的话 - 如何?我发现的唯一的例子是有关传递值类型为构造函数的参数,而不是引用类型。
我感觉我失去了一些东西明显...
当前设置如下:
在Global.asax中的Application_Start我叫下面的方法:
受保护的虚拟IWindsorContainer InitializeServiceLocator()
{
IWindsorContainer集装箱=新WindsorContainer();
ControllerBuilder.Current.SetControllerFactory(新WindsorControllerFactory(容器));
container.RegisterControllers(typeof运算(HomeController中).Assembly);
ComponentRegistrar.AddComponentsTo(容器);
返回容器中;
}
ComponentRegistrar:
公共静态无效AddComponentsTo(IWindsorContainer容器)
{
//添加其他成分.....
container.AddComponentLifeStyle< IActionInvoker ,WindsorActionInvoker>(LifestyleType.PerWebRequest);
}
WindsorActionInvoker:
公共类WindsorActionInvoker:ControllerActionInvoker,IActionInvoker
{
只读IWindsorContainer容器;
公共WindsorActionInvoker(IWindsorContainer容器)
{
this.container =容器;
}
保护覆盖ActionExecutedContext InvokeActionMethodWithFilters(
ControllerContext controllerContext,
的IList< IActionFilter>过滤器,
ActionDescriptor actionDescriptor,
的IDictionary<字符串,对象>参数)
{
的foreach(IActionFilter actionFilter滤镜)
{
container.Kernel.InjectProperties(actionFilter);
}
返回base.InvokeActionMethodWithFilters(controllerContext,过滤器,actionDescriptor,参数);
}
}
WindsorControllerFactory:
公共类WindsorControllerFactory:DefaultControllerFactory
{
私人只读IWindsorContainer容器;
公共WindsorControllerFactory(IWindsorContainer容器)
{
如果(集装箱== NULL)
{
抛出新的ArgumentNullException(容器);
}
this.container =容器;
}
公共覆盖无效ReleaseController(一个IController控制器)
{
无功一次性=控制器IDisposable的;
如果(一次性!= NULL)
{
disposable.Dispose();
}
this.container.Release(控制器);
}
保护覆盖一个IController GetControllerInstance(RequestContext的RequestContext的,类型controllerType)
{
如果(controllerType == NULL)
{
返回base.GetControllerInstance(RequestContext的,controllerType);
}
无功控制器= this.container.Resolve(controllerType)作为控制器;
如果(控制器!= NULL)
{
controller.ActionInvoker = this.container.Resolve< IActionInvoker>(this.container);
}
返回控制器;
}
}
更新
块引用>
我错过了一个细微之处:我试图用这种行为为以下内容:
公共类CustomAuthorize:AuthorizeAttribute {...}
这。不执行
IActionFilter
增加了以下到WindsorActionInvoker:
保护覆盖AuthorizationContext InvokeAuthorizationFilters(controllerContext controllerContext,IList的<个IAuthorizationFilter>过滤器,actionDescriptor actionDescriptor)
{
的foreach(个IAuthorizationFilter authorizeFilter滤镜)
{
this.kernel.InjectProperties(authorizeFilter);
}
返回base.InvokeAuthorizationFilters(controllerContext,过滤器,actionDescriptor);
}
根据需要这现在工作。由于克里斯蒂亚诺,因为这是他这把我在正确的道路上慷慨地提供代码分析。
解决方案Global.asax中
私有静态无效bootstrapContainer()
{
容器=新WindsorContainer()
.Install( FromAssembly.This());
变种的ControllerFactory =新WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(的ControllerFactory);
}
安装/灌装容器
公共类ControllersInstaller:IWindsorInstaller
{
#地区IWindsorInstaller会员
公共无效安装(IWindsorContainer容器,IConfigurationStore店)
{
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>()
。如果(Component.IsInSameNamespaceAs<&HomeController的GT;())
。如果(T => t.Name.EndsWith(控制器))
.Configure((C => c.LifeStyle.Transient)));
}
#endregion
}
WindsorControllerFactory
使用系统;
使用的System.Web;
使用System.Web.Mvc;
使用System.Web.Routing;
使用Castle.MicroKernel;
公共类WindsorControllerFactory:DefaultControllerFactory
{
私人只读的iKernel内核;
公共WindsorControllerFactory(内核的iKernel)
{
this.kernel =内核;
}
公共覆盖无效ReleaseController(一个IController控制器)
{
kernel.ReleaseComponent(控制器);
}
保护覆盖一个IController GetControllerInstance(RequestContext的RequestContext的,类型controllerType)
{
如果(controllerType == NULL)
{
罚球新HttpException(404的String.Format(以下简称控制器路径{0}可能不会被发现。requestContext.HttpContext.Request.Path));
}
一个IController一个IController =(一个IController)kernel.Resolve(controllerType);
//新的代码
如果(一个IController是控制器)
{
((控制器)一个IController).ActionInvoker = kernel.Resolve< IActionInvoker>();
}
返回一个IController;
}
}
WindsorActionInvoker
命名空间WindsorExtensions.Mvc
{
公共类WindsorActionInvoker:ControllerActionInvoker
{
只读的iKernel内核;
公共WindsorActionInvoker(内核的iKernel)
{
this.kernel =内核;
}
保护覆盖ActionExecutedContext InvokeActionMethodWithFilters(
ControllerContext controllerContext
,IList的< IActionFilter>过滤器
,ActionDescriptor actionDescriptor
,IDictionary的<字符串对象>参数)
{
的foreach(IActionFilter actionFilter滤镜)
{
kernel.InjectProperties(actionFilter);
}
返回base.InvokeActionMethodWithFilters(controllerContext,过滤器,actionDescriptor,参数);
}
}
公共静态类WindsorExtension
{
公共静态无效InjectProperties(此的iKernel内核对象目标)
{
VAR类型= target.GetType();
的foreach(在type.GetProperties(BindingFlags.Public VAR物业| BindingFlags.Instance))
{
如果(property.CanWrite&安培;&安培; kernel.HasComponent(property.PropertyType))
{
VAR值= kernel.Resolve(property.PropertyType);
尝试{property.SetValue(目标,价值,NULL); }
赶上(异常前)
{
VAR消息=的String.Format(错误设置属性{0}的类型{1},以了解更多信息,请参阅内部异常。属性。名称,type.FullName);
抛出新ComponentActivatorException(消息,前);
}
}
}
}
}
}
AgencyAuthorizeAttribute
命名空间WpRegistration.Web.Filters
{
[ AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,的AllowMultiple = FALSE,继承= TRUE)]
公共密封类AgencyAuthorize:ActionFilterAttribute
{
CurrentUserService _currentUserSvc;
公共AgencyAuthorize(){}
公共服务CurrentUserService
{
{返回_currentUserSvc; }
组
{
this._currentUserSvc =价值;
}
}
I am trying to use the approach from this article, but I am missing something - I am currently getting an error within WindsorControllerFactory.GetControllerInstance when it tries to resolve IActionInvoker since WindsorActionInvoker has a dependency on IWindsorContainer.
Given that WindsorControllerFactory already has a reference to IWindsorContainer, could I pass that reference in? If so - how? The only examples I have found are about passing value types as constructor parameters, not reference types.
I'm feeling I'm missing something obvious...
Current setup as follows: Within Global.asax Application_Start I call the following method:
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; } }
Update
I missed a subtlety: I was trying to use this behaviour for the following:
public class CustomAuthorize : AuthorizeAttribute {...}
which doesn't implement
IActionFilter
.Added the following to 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); }
This now works as required. Thanks to Cristiano since it was analysis of his kindly provided code which put me on the right path.
解决方案Global.asax
private static void bootstrapContainer() { container = new WindsorContainer() .Install(FromAssembly.This()); var controllerFactory = new WindsorControllerFactory(container.Kernel); ControllerBuilder.Current.SetControllerFactory(controllerFactory); }
Installer / filling container
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; } }
这篇关于温莎城堡 - 注射IActionInvoker执行问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!