【问题标题】:Can Autofac inject dependencies into layout view files?Autofac 可以将依赖项注入到布局视图文件中吗?
【发布时间】:2012-07-21 15:46:22
【问题描述】:

我正在尝试将依赖项注入到共享布局视图页面中,以避免在使用该布局的每个视图中都必须这样做。

我已经按照 wiki 中的 guidance 将依赖项注入视图,但该属性始终为空。

Autofac 可以将属性注入到作为布局文件的自定义视图页面中吗?

这是我的设置。 自定义视图页面

namespace MyApp
{
    using System.Web.Mvc;

    public abstract class CustomViewPage : WebViewPage
    {
        public IHelper Helper { get; set; }
    }
}

~/Views/Shared/_Layout.cshtml

@inherits MyApp.CustomViewPage
<!DOCTYPE html>
<html>
...
@if(this.Helper.HasFoo()){@Html.ActionLink("Bar")}

全球注册...

builder.RegisterType<Helper>().AsImplementedInterfaces();
builder.RegisterModelBinderProvider();
builder.RegisterFilterProvider();
builder.RegisterModule(new AutofacWebTypesModule());
builder.RegisterSource(new ViewRegistrationSource());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

使用布局的“子”视图不是从 CustomViewPage 派生的。

【问题讨论】:

标签: asp.net-mvc dependency-injection asp.net-mvc-4 autofac


【解决方案1】:

大多数解决方案将只是 DependencyResolver.Current.GetService 调用的包装,因此直接从布局调用它可能更容易:

@{
    var helper = DependencyResolver.Current.GetService<IHelper>();
}
...
@if (helper.HasFoo()) { @Html.ActionLink("Bar") }
...

这种方式也有助于使页面模型更具 SRP,因为可以避免将服务例程/模型与业务例程/模型混合。

【讨论】:

    【解决方案2】:

    这是一个适用于大多数 DI 框架的小工作。

    先稍微调整一下你的CustomPageView:

    public abstract class CustomViewPage : WebViewPage
    {
        public IHelper Helper { 
            get { return ViewData[Helper.ViewDataKey] as IHelper; }    
        }
    
    }
    

    现在需要将依赖关系引入到您的 ViewData 中,引入一个属性来执行此操作:

    public sealed class HelperAttribute : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var viewResult = filterContext.Result as ViewResult;
            if (viewResult != null)
                viewResult.ViewData.Add(Helper.ViewDataKey, GetHelperFromIoC());
    
            base.OnResultExecuting(filterContext);
        }
    }
    

    在你的动作方法或控制器上:

    [Helper]
    public ActionResult Index()
    {
        return View();
    }
    

    在您看来,您现在应该可以按预期使用您的 Helper:

     @Helper.HelloWorld()
    

    请参阅this blog 获取原始帖子。

    【讨论】:

      【解决方案3】:

      只需创建部分页面并将其插入布局页面:

      @Html.Partial("_MyPartialPage");
      

      依赖被注入部分页面。

      【讨论】:

        【解决方案4】:

        不仅仅是 AutoFac,基本上你无法在布局中实现 DI。您可能需要引用 CustomViewPage 中的 IOC 容器来解决依赖关系。

        除非它是REALYYY REQUIRED,否则请避免在视图中使用 DI(只是我的观点)。

        从我的角度来看,我没有看到太多好处。我认为您不会为基本视图页面类编写单元测试吗?除非有任何特殊原因,否则请避免。与其依赖于容器,不如依赖于具体的实现。

        【讨论】:

        • 关于为什么不能 DI 进入布局的任何参考或背景?
        • @Josh 如上所述,这是我和许多其他人的意见,我从来没有说过你不能只是说这可能不是最好的主意......为什么不这样做的几个原因,它会是很难进行单元测试,这取决于您使用的 IoC 库,您需要访问 HttpContext 来解析容器,并且您可能最终会遇到您的视图直接与服务对话的情况,因此会破坏 MVC 模式。这取决于每个人他们如何做事,我并不是说你不能只是说你可能想重新考虑设计并确保没有更好的选择
        • @Joe_DM 您能否将您的编辑发布为新答案?
        • @VJAI 抱歉,但看起来编辑后的更改已丢失,不知道为什么:( 如果有某种方法可以在历史上找到它们,我会很高兴,否则重新做的工作太多- 抱歉,从头开始创建。
        • @VJAI 我知道发生了什么,我已经编辑了别人的答案,我认为这是我的答案:O 如果有办法取回我在答案中输入的代码,我会很高兴作为新答案发布。
        【解决方案5】:

        对于没有参数的结果,您不需要扩展您的 WebViewPage 来传递数据。 我会这样解决它: 1.声明一个派生自ActionFilter的类HelperActionFilter,通过属性http://docs.autofac.org/en/latest/integration/mvc.html向它注入你的服务 2.在HelperActionFilter.OnActionExecuting里面设置ViewBag.HasFoo在layout里面检查一下。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-09
          • 1970-01-01
          • 2011-01-10
          相关资源
          最近更新 更多