Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Unity将依赖项注入自定义ActionFilter_C#_Asp.net Mvc 3_Dependency Injection_Unity Container - Fatal编程技术网

C# 使用Unity将依赖项注入自定义ActionFilter

C# 使用Unity将依赖项注入自定义ActionFilter,c#,asp.net-mvc-3,dependency-injection,unity-container,C#,Asp.net Mvc 3,Dependency Injection,Unity Container,目前,我有一个定制的ControllerFactory,我将Unity容器注入其中: protected override ActionExecutedContext InvokeActionMethodWithFilters( ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor,

目前,我有一个定制的ControllerFactory,我将Unity容器注入其中:

protected override ActionExecutedContext InvokeActionMethodWithFilters(
        ControllerContext controllerContext,
        IList<IActionFilter> filters,
        ActionDescriptor actionDescriptor,
        IDictionary<string, object> parameters)
{
    var builtUpFilters = new List<IActionFilter>();

    foreach (IActionFilter actionFilter in filters)
    {
        builtUpFilters.Add(_container.BuildUp<IActionFilter>(actionFilter));
    }

    return base.InvokeActionMethodWithFilters(controllerContext, builtUpFilters, actionDescriptor, parameters);
}
在global.asax应用程序_Start()中:

在控制器工厂中,我将控制器设置为使用自定义ActionInvoker,如下所示:

protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
    var controller = base.GetControllerInstance(requestContext, controllerType) as Controller;

    if (controller != null)
        controller.ActionInvoker = new UnityActionInvoker(_container);

    return controller;
}
最后,在我的自定义ActionInvoker中,我尝试使用ActionInvokers容器构建正在调用的操作:

protected override ActionExecutedContext InvokeActionMethodWithFilters(
        ControllerContext controllerContext,
        IList<IActionFilter> filters,
        ActionDescriptor actionDescriptor,
        IDictionary<string, object> parameters)
{
    var builtUpFilters = new List<IActionFilter>();

    foreach (IActionFilter actionFilter in filters)
    {
        builtUpFilters.Add(_container.BuildUp<IActionFilter>(actionFilter));
    }

    return base.InvokeActionMethodWithFilters(controllerContext, builtUpFilters, actionDescriptor, parameters);
}
protected override ActionExecutedContext InvokeActionMethodWithFilters(
ControllerContext ControllerContext,
IList过滤器,
ActionDescriptor ActionDescriptor,
(字典参数)
{
var builtUpFilters=新列表();
foreach(过滤器中的IActionFilter actionFilter)
{
builtUpFilters.Add(_container.build(actionFilter));
}
返回base.InvokeActionMethodWithFilters(controllerContext、builtUpFilters、actionDescriptor、参数);
}
下面是正在构建的一个ActionFilter的示例:

public class PopulatRolesAttribute : ActionFilterAttribute, IActionFilter
{
    private const string RolesKey = "roles";

    [Dependency]
    public Func<IMetadataService> Service { get; set; }

    public PopulatRolesAttribute()
    {
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.Controller.ViewData[RolesKey] == null)
        {
            filterContext.Controller.ViewData[RolesKey] = Service().GetRoles();
        }
    }
}
public类populateRolesAttribute:ActionFilterAttribute,IActionFilter
{
私有常量字符串RolesKey=“roles”;
[依赖性]
公共函数服务{get;set;}
公共PopulatorLesAttribute()
{
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
if(filterContext.Controller.ViewData[RolesKey]==null)
{
filterContext.Controller.ViewData[RolesKey]=Service().GetRoles();
}
}
}
问题是,我的自定义ActionFilterAttribute上的公共属性从未注入任何内容,它在执行时仍然为null!我看不出为什么容器没有正确构建过滤器。正在注入的类型已正确注册,如下所示:

container.RegisterInstance(new ChannelFactory<IMetadataService>(
    new BasicHttpBinding(),
    new EndpointAddress("http://example.com/ABSApplication/MetadataService.svc")));

container.RegisterInstance<Func<IMetadataService>>(
    () => container.Resolve<ChannelFactory<IMetadataService>>().CreateChannel());
container.RegisterInstance(新通道工厂)(
新的BasicHttpBinding(),
新端点地址(“http://example.com/ABSApplication/MetadataService.svc")));
容器.RegisterInstance(
()=>container.Resolve().CreateChannel());

并且也被注入到应用程序的其他地方(尽管不是通过.build)。这与下面的过程差不多。我错过了拼图的哪一部分?

我会稍微改变一下。我想:

  • 安装unity.mvc3 nuget软件包

  • 调用bootstrapped.initialise(),如包添加到项目中的txt文档中所述

  • 在初始化到具体类型中定义IMetadataService映射

  • 将IMetadataService添加到构造函数中

  • 您的实现和您引用的文章之间的区别在于您使用了Func,我不确定这是否会给这里的混合带来不同的问题。我不得不想象它是这样的,因为上面的方法(没有Func)对我来说很好

    编辑: Brad Wilson的代码对我来说很好:

    适用部分(请参见上面的链接)

    Global.asax.cs

    
    protected void Application_Start() {
        // ...
    
        var oldProvider = FilterProviders.Providers.Single(
            f => f is FilterAttributeFilterProvider
        );
        FilterProviders.Providers.Remove(oldProvider);
    
        var container = new UnityContainer();
        var provider = new UnityFilterAttributeFilterProvider(container);
        FilterProviders.Providers.Add(provider);
    
        // ...
    }
    
    过滤器本身:

    
    using System;
    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    
    public class InjectedFilterAttribute : ActionFilterAttribute {
    
        [Dependency]
        public IMathService MathService { get; set; }
    
        public override void OnResultExecuted(ResultExecutedContext filterContext) {
            filterContext.HttpContext.Response.Write(
                String.Format("The filter says 2 + 3 is {0}.

    ", MathService.Add(2, 3)) ); } }

    我很欣赏Unity.Mvc3包的方向——它很好地使用Unity封装了Mvc3的依赖项解析。然而,我不认为它解决了我的问题。如果我在控制器中有一个用过滤器修饰的方法,比如:
    [PopulatRoles]public ActionResult Add(){
    如何在PopulateRoles ActionFilterAttribute上实现注入?我不能使用构造函数注入,因为它是一个属性,也不能使用它的构造函数。因此,我需要在创建属性时构建它。作为附录,我看到ninject做了完全不同的事情,允许构造函数注入关于过滤器,但是我不确定这是否可以通过Unity实现。过滤器是在MVC内部解决的,我必须在这里尝试一个快速测试。实际上,这应该在这里起作用-在聚会上很晚才尝试,但是
    Unity Bootstrapper for ASP.NET MVC
    包为您完成了所有这些工作。出于好奇,我为什么不这样做呢例如,验证请求、预授权请求等并缓存它们(会话等)因此,当用户登录时,每个请求都有它们?我的初衷是封装此功能,以便在操作需要时添加它。如果经过审查,我打算大量使用过滤器检索的数据,我肯定会全局缓存它,以便在整个应用程序中重用。这是实际上,不管如何重用,这看起来都是一个更简单的解决方案!我仍然很好奇为什么
    容器。但是,构建
    不起作用。我确实找到了这个示例,很快就会查看它。源代码也可以在那里下载,我看到了那篇文章,这促使我进一步提出问题这里。查看那篇文章中的代码,它似乎有点不完整。我看不到自定义IFilterProvider连接在哪里。当然,仅仅在容器中注册它是不够的,它不能被使用。它确实避免了上面使用Building发布的问题。如果我不能很快得到关于为什么Building不能在orig中工作的响应最后,我将接受您的回答,因为我很感谢您确认我的想法与其他开发人员的想法相同:)
    
    
    using System.Collections.Generic;
    using System.Web.Mvc;
    using Microsoft.Practices.Unity;
    
    public class UnityFilterAttributeFilterProvider : FilterAttributeFilterProvider {
        private IUnityContainer _container;
    
        public UnityFilterAttributeFilterProvider(IUnityContainer container) {
            _container = container;
        }
    
        protected override IEnumerable GetControllerAttributes(
                    ControllerContext controllerContext,
                    ActionDescriptor actionDescriptor) {
    
            var attributes = base.GetControllerAttributes(controllerContext,
                                                          actionDescriptor);
            foreach (var attribute in attributes) {
                _container.BuildUp(attribute.GetType(), attribute);
            }
    
            return attributes;
        }
    
        protected override IEnumerable GetActionAttributes(
                    ControllerContext controllerContext,
                    ActionDescriptor actionDescriptor) {
    
            var attributes = base.GetActionAttributes(controllerContext,
                                                      actionDescriptor);
            foreach (var attribute in attributes) {
                _container.BuildUp(attribute.GetType(), attribute);
            }
    
            return attributes;
        }
    }