注入具有构造函数依赖项的记录器

时间:2017-02-06 07:03:30

标签: c# dependency-injection asp.net-core

我尝试重构一些代码,以便通过startup.cs中的映射服务使用.NET Core依赖注入。我想在这里注入一个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);
        }
   }

3 个答案:

答案 0 :(得分:8)

  

但是它需要构造函数中的上下文。

让应用程序组件的构造依赖于运行时数据是一种反模式,如here所述。那篇文章描述了如何解决这些问题。

在您的情况下,这可能意味着您的组件应该依赖于ASP.NET Core的IHttpContextAccessor抽象,而这是参考文章中描述的模式。

或者,如本文所述,您可以使用Log方法将所需的运行时数据传递给记录器。

答案 1 :(得分: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 Core中的属性同时仍将依赖项注入基础操作过滤器的方法。我还将在即将到来的DevIQ.com上的ASP.NET核心快速入门课程中介绍这一点(本月末查找)。

答案 2 :(得分: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);
    }

}