Ошибка активации атрибута Autofac по атрибутам

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

Я создаю довольно простой сайт ASP.NET MVC 4, и план заключается в использовании журнала ActionFilterAttribute. У меня есть класс DataAccessProvider, который открывает транзакции с базой данных и предоставляет экземпляры единицы работы, и я пытаюсь внедрить его в атрибут фильтра.

Документация говорит, что достаточно просто позвонить RegisterFilterProvider() и убедиться, что зарегистрированы соответствующие типы. В нем конкретно говорится, что нет необходимости регистрировать атрибут, но я пробовал как с, так и без. В настоящее время мой код выглядит примерно так:

var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());

builder.Register(x => new EntityAccessProvider())
    .As<IDataAccessProvider>()
    .InstancePerHttpRequest();

builder.RegisterType<DebugLogAttribute>().PropertiesAutowired();
// ^ I've tried it with and without this line

builder.RegisterFilterProvider();
var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

Пример в документах затем просто помещает свойство в фильтр, поэтому я сделал то же самое:

public class DebugLogAttribute : ActionFilterAttribute
{
    private IDataAccessProvider DataAccess { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext) { ... }
    public override void OnActionExecuted(ActionExecutedContext filterContext) { ... }
}

Документы говорят, что все требуется - даже не конструктор для ввода; это делается путем инъекции свойств. Однако, когда я запускаю этот код, свойство DataAccess всегда null; Autofac, кажется, игнорирует это. Я знаю, что регистрация работает правильно, потому что она правильно вводит EntityAccessProvider в мои контроллеры, но не работает для атрибутов. Что мне не хватает?

Ответ 1

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

[DebugLogAttribute]
public class HOmeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

internal class DebugLogAttribute : ActionFilterAttribute
{
    public IDataAccessProvider DataAccess { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        Debugger.Break();
    }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        Debugger.Break();
    }
}

internal interface IDataAccessProvider {}

internal class DataAccessProvider:IDataAccessProvider {}

Ответ 2

У меня была такая же проблема в ядре asp dotnet, но текущее решение (обнародование), похоже, не работает. Что я нахожу странным, так это то, что комментарий ниже касается веб-API, но я использую обычный ASP.NET Core MVC (MVC6). Так что, если у кого-то есть такая же проблема, попробуйте решение ниже.

https://docs.autofac.org/en/latest/integration/webapi.html#standard-web-api-filter-attributes-are-singletons

В отличие от поставщика фильтров в MVC, в Web API нельзя указывать, что экземпляры фильтра не должны кэшироваться. Это означает, что все атрибуты фильтра в Web API фактически являются единичными экземплярами, которые существуют в течение всего времени жизни приложения.

public override async Task OnActionExecutionAsync(
            ActionExecutingContext context,
            ActionExecutionDelegate next)
        {
            MyService = context.HttpContext.
                               RequestServices.GetService(typeof(IMyService)) as IMyService;
        }