将 NLog 直接注入 .Net Core 项目总是 NULL?
Posted
技术标签:
【中文标题】将 NLog 直接注入 .Net Core 项目总是 NULL?【英文标题】:Direct Injection of NLog into .Net Core project always NULL? 【发布时间】:2020-11-04 08:55:58 【问题描述】:我是 .Net Core(使用 3.1)并使用依赖注入的新手。我能够在 Web API 控制器中设置 NLog,但现在我正试图让 NLog 按照我在 API 控制器中所做的基本操作在单独的业务类中工作。我不断收到有关记录器为 NULL 的错误,当我在 _logger 和 _config 上设置断点时,果然它们为 NULL。我不确定我在这里缺少什么。
这是我的商务舱,我认为我的设置正确,但显然没有。
public class ShiftBLL
private static IConfiguration _config;
private static ILogger<ShiftBLL> _logger;
public ShiftBLL(ILogger<ShiftBLL> logger, IConfiguration config)
_config = config;
_logger = logger;
public static List<AppsShift> GetShifts(string station, string shiftDate)
_logger.LogInformation("Staion: 0 | ShiftDate: 1", station, shiftDate);
*code removed for clarity. The app breaks on the initial call of _logger.
修复
我从 ShiftBLL 类以及本地参数中删除了“静态”。然后我必须在我的控制器中创建一个 ShiftBLL 对象,并从控制器中传入记录器和配置,在控制器中我有 DI 在 ShiftBLL 中工作。我最终在我的控制器中得到了这个:
ShiftBLL BLL = new ShiftBLL(_logger, _config);
listShifts = BLL.GetShifts(station, shiftDate);
这是我更新的 ShiftBLL:
public class ShiftBLL
private IConfiguration _config;
private readonly ILogger _logger;
public ShiftBLL(ILogger logger, IConfiguration config)
_config = config;
_logger = logger;
public List<AppsShift> GetShifts(string station, string shiftDate)
_logger.LogInformation("Staion: 0 | ShiftDate: 1", station, shiftDate);
我仍然对依赖注入感到头疼。
【问题讨论】:
您可以尝试从类字段中删除“静态”关键字吗?它们在设计上不应该是静态的。编辑:我刚刚注意到,即使 GetShifts 也是静态的,它是从课堂外调用的吗?你能分享一下 GetiShifts 是如何被调用的代码吗? 所以我从类中删除了静态并创建了一个 ShiftBLL 的对象。看起来这可能奏效了。我本可以发誓我今天早些时候尝试过,它没有用,但看起来知道。这是我在 Controller 中创建的...ShiftBLL BLL = new ShiftBLL(_logger, _config); 像这样声明‘私有只读 ILogger使用 DI 时,DI 容器会在需要时插入所有依赖项的参数。
我将尝试用一个简化的例子来解释:
public class MyClass
public MyClass(ShiftBLL shiftBll)
..
解析MyClass时,DI容器会做:
-
查找创建 MyClass 实例所需的所有依赖项 - 在本例中:
ShiftBLL
在此ILogger
和IConfiguration
中找到创建ShiftBLL
所需的所有依赖项
查找ILogger
和IConfiguration
的注册(因为它们是接口)以及依赖项等。
创建ILogger
和IConfiguration
的实例(通过注册),通过将实例注入构造函数来创建ShiftBLL
的实例
创建MyClass
的实例并注入 ShiftBLL 的实例。
所以有了这个链,你所有的构造函数依赖都被创建了。
但是,如果您在ShiftBLL
中使用静态方法,您不确定是否曾调用过 ShiftBLL(带有 ILogger)的构造函数 - 因此 ILogger 字段可能是 null
。 .
所以要解决这个问题,你可以这样做:
使方法非静态,或 将所有依赖项(ILogger)作为参数发送到静态方法【讨论】:
【参考方案2】:您混淆了静态方法调用和依赖注入。我会说尽可能避免使用静态方法,无论如何,当您使用静态方法时,您无法访问通过依赖注入注入的依赖。例如,您无法从 GetShifts 访问 _logger,因为您没有 ShiftBll 的实例,而且您静态调用它的事实意味着它的构造函数永远不会被调用。
这是一个关于如何设计类及其依赖项以及如何注册它们的工作示例。
public class AController : Controller
private readonly ILogger<AController> _logger;
private readonly ShiftBll _shiftBll;
public AController(ILogger<AController> logger, ShiftBll shiftBll)
_logger = logger;
_shiftBll = shiftBll;
//I'm pretty sure you didn't inject the dependency here
//you preferred to use a static reference, but it is not correct in this case
public ActionResult AnAction()
var shifts = _shiftBll.GetShifts("aStation", "aShiftDate");
public class ShiftBLL
private readonly IConfiguration _config; //not static
private readonly ILogger<ShiftBLL> _logger; //not static
public ShiftBLL(ILogger<ShiftBLL> logger, IConfiguration config)
_config = config;
_logger = logger;
public List<AppsShift> GetShifts(string station, string shiftDate) //not static
_logger.LogInformation("Staion: 0 | ShiftDate: 1", station, shiftDate);
*code removed for clarity. The app breaks on the initial call of _logger.
.NET Core DI 自动注册控制器,但您必须手动注册自己的服务。为此,请进入 Startup.cs 的 ConfigureServices 方法并添加
services.AddScoped<ShiftBll>();
现在您可以使用 AController 中的 ShiftBll。
【讨论】:
“当你使用静态方法时,你不能访问通过依赖注入注入的依赖”——这是错误的。 当然你可以访问静态成员。只是_logger
和 _config
在调用构造函数之前将是“null” :( 但我同意 - 这里没有明显需要“静态”,删除“静态”应该可以解决问题。
@paulsm4 依赖关系可以是暂时的,这意味着消费者的每个实例都将具有不同的依赖关系实例。你将如何使它与静态引用一起工作?实现这一点的唯一方法是通过静态服务定位器,这是 .NET Core 决定不包含在设计中的。此外,服务位置不是依赖注入。我很乐意澄清您对此的任何疑问。
请改写您的回复。在我看来,您是在暗示“静态成员”本质上与 .Net Core 的 DI 不兼容。我不敢相信这是真的。请不要明确地说“尽可能避免使用静态方法”。这只是一个糟糕的建议:(关注这里的具体问题(构造函数从未被调用,因此 DI 从未发生),您正确诊断。
@paulsm4 你能告诉我一个使用从 DI 注入的依赖项的静态方法的工作示例吗?语言或框架无关紧要
我不知道为什么你被标记为基本上是一个“正确”的答案。我不知道为什么 Caverman 没有“接受”它(尽管我很欣赏他的更新——这是一种很好的做法 :))。而且我不知道您为什么不更新您的回复以更多地关注直接问题(“静态”不合适),也许澄清“静态”通常是完全合适的。只是不在这里,现在不是 :( 我特别不同意“尽可能避免使用静态方法”这句话 :(以上是关于将 NLog 直接注入 .Net Core 项目总是 NULL?的主要内容,如果未能解决你的问题,请参考以下文章
Net Core 2.1 日志记录框架NLog+Mysql配置