使用构造函数依赖项注入日志记录器

6

我正在尝试通过在startup.cs中映射服务来使用.NET Core依赖注入重构一些代码。我想在这里注入一个IRequestDatabaseLogger而不是新建它。但是它需要在构造函数中的上下文。我该如何实现这一点?即使没有DI框架,甚至在没有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
在属性中不要执行任何有用的操作。如此解释在这里在这里 - Steven
相关链接:https://dev59.com/Tl0a5IYBdhLWcg3wzbjV#29916075 - Steven
2
我认为你的意思是“避免”,而不是“防止”(做任何有用的事情)... - ssmith
3个回答

8
然而,构造函数需要上下文。让应用程序组件的构建依赖于运行时数据是一种反模式,如此处所述。该文章描述了如何解决这些问题。在您的情况下,这可能意味着您的组件应该依赖于ASP.NET Core的IHttpContextAccessor抽象,这是引用文章中描述的一种模式。或者,如文章所述,您可以使用其Log方法将所需的运行时数据传递给记录器。

2
您需要使用TypeFilter来实现这一点,并将具有依赖关系(在此情况下是记录器或上下文)的过滤器包装在过滤器内。我在我的ASP.NET Core Filters MSDN文章中展示了一个详细的例子。相关源代码在这里(查看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 Core快速入门课程中进行了介绍(请寻找本月底发布)。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接