2017-02-06 4 views
5

Я пытаюсь реорганизовать некоторый код, чтобы использовать инъекцию зависимости .NET Core через службы отображения в startup.cs. Я хотел бы ввести здесь IRequestDatabaseLogger вместо того, чтобы его обновлять. Однако для этого требуется контекст в конструкторе. Как я могу это достичь? Возможно ли это без рамки DI или даже тогда?Ввод регистратора с зависимостями конструктора

public class ActionFilter : ActionFilterAttribute 
    { 
     public override void OnActionExecuting(ActionExecutingContext context) 
     { 
      var requestDatabaseLogger = new RequestDatabaseLogger(context); 
      long logId = requestDatabaseLogger.Log(); 

      context.HttpContext.AddCurrentLogId(logId); 

      base.OnActionExecuting(context); 
     } 
    } 
+2

Запретить делать что-либо полезное в атрибутах. Атрибуты должны быть пассивными, как описано [здесь] (http://blog.ploeh.dk/2014/06/13/passive-attributes/) и [здесь] (https://www.cuttingedge.it/blogs/steven /pivot/entry.php?id=98). – Steven

+0

Связанный: https://stackoverflow.com/a/29916075/264697 – Steven

+1

Я думаю, вы имеете в виду * Избегайте * Не предотвращать (делать что-нибудь полезное) ... – ssmith

ответ

8

Однако это требует контекст в конструкторе.

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

В вашем случае это, вероятно, означает, что ваш компонент должен зависеть от абстракции ASP.NET Core IHttpContextAccessor, что является шаблоном, описанным в статье, на которую делается ссылка.

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

0

Внесите в конструктор RequestDatabaseLoggerFactory, который может быть использован для создания экземпляра RequestDatabaseLogger.

public interface IRequestDatabaseLoggerFactory { 
    IRequestDatabaseLogger Create(ActionExecutingContext context); 
} 
public class RequestDatabaseLoggerFactory : IRequestDatabaseLoggerFactory { 
    public IRequestDatabaseLogger Create(ActionExecutingContext context) { 
     return new RequestDatabaseLogger(context); 
    } 
} 

public class ActionFilter : ActionFilterAttribute 
{ 
    public ActionFilter(IRequestDatabaseLoggerFactory factory) { 
     _factory = factory; 
    } 

    private readonly IRequestDatabaseLoggerFactory _factory; 

    public override void OnActionExecuting(ActionExecutingContext context) 
    { 
     var requestDatabaseLogger = _factory.Create(context); 
     long logId = requestDatabaseLogger.Log(); 

     context.HttpContext.AddCurrentLogId(logId); 

     base.OnActionExecuting(context); 
    } 

}

+1

Я советую использовать абстракции фабрики, как показано здесь, как объяснено [ здесь] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=100). – Steven

2

Вы должны использовать TypeFilter для достижения этой цели, и обернуть фильтр, который имеет зависимость (в данном случае на регистраторе или контекста) внутри фильтра. Я приведу подробный пример этого в моем MSDN Article on ASP.NET Core Filters. Связанный исходный код: here (смотрите фильтр ValidateAuthorExists).

Вот что это может выглядеть в вашем сценарии:

public class MyFilterAttribute : TypeFilterAttribute 
{ 
    public MyFilterAttribute():base(typeof(MyFilterImpl)) 
    { 
    } 

    private class MyFilterImpl : IAsyncActionFilter 
    { 
     public MyFilterImpl(*inject dependencies here*) 
     {} 
    } 
} 

Это, как вы можете использовать атрибуты в .NET Ядра в то же время инъекционные зависимостей в фильтр основного действия. Я также расскажу об этом в своем предстоящем курсе ASP.NET Core Quickstart на DevIQ.com (ищите его в конце этого месяца).

 Смежные вопросы

  • Нет связанных вопросов^_^