Может ли Autofac вводить зависимости в файлы вида макета?

Я пытаюсь ввести зависимость на страницу совместного просмотра макета, чтобы избежать необходимости делать это во всех представлениях, которые используют макет.

Я следил за указаниями в вики для ввода зависимостей в представлениях, но свойство всегда равно нулю.

Может ли Autofac вводить свойства в пользовательскую страницу просмотра, которая является файлом макета?

Здесь моя настройка. CustomViewPage

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

Представления "child", которые используют макет, не выводятся из CustomViewPage.

Ответ 1

Большинство решений будет просто обернуть вокруг вызова DependencyResolver.Current.GetService, поэтому было бы проще вызвать его непосредственно из макета:

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

Кроме того, этот способ помогает сделать модель страницы более SRP, поскольку может избежать смешивания сервисных процедур/моделей и бизнес-приложений.

Ответ 2

Это не только с AutoFac, вы не можете достичь DI в макетах. Для разрешения зависимостей может потребоваться ссылка на контейнер IOC в CustomViewPage.

Если это НЕ РЕАЛЬНО НЕОБХОДИМО, просто избегайте DI во взглядах (просто мое мнение).

С моей точки зрения, я не вижу больших преимуществ. Думаю, вы не собираетесь писать модульные тесты для класса страницы базового представления? если нет какой-либо особой причины, просто избегайте этого. Вместо того, чтобы иметь зависимость от контейнера, лучше иметь зависимости с конкретными реализациями.

Ответ 3

Вот небольшая работа, которая будет работать с большинством инфраструктур 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.HelloWorld()

См. Этот блог для оригинального сообщения.

Ответ 4

Для результата без параметров вам не нужно расширять WebViewPage для передачи данных. Я решил бы это следующим образом: 1. Объявите класс HelperActionFilter, полученный из ActionFilter, добавьте свою службу к нему через свойство http://docs.autofac.org/en/latest/integration/mvc.html 2. Inside HelperActionFilter.OnActionВыполните установку ViewBag.HasFoo проверьте его в макете.

Ответ 5

Просто создайте частичную страницу и вставьте ее в макет страницы:

@Html.Partial("_MyPartialPage");

Зависимости вводятся на частичные страницы.