在ASP.NET Core中,默认解析程序将解析控制器中的Microsoft.Extensions.Logging.ILogger<MyClass>
。
假设我创建了一个从控制器调用的新.NET标准库。
如何将Microsoft.Extensions.Logging
实例传递给它?
new()
,如何创建班级的ILogger<MyClass2>
个实例?ILogger<T>
手动自动化,我可以将其传递到我的库中吗? 答案 0 :(得分:1)
有时候,依赖注入不可用-或者当您处在不应该使用DI的环境中(例如单元测试,您将明确定义每个注入的服务),同理某些形式的集成测试。
在这种情况下-如果您不关心日志记录(例如,在进行原型设计或实验时),请使用NullLogger
内置的Microsoft.Extensions.Logging.Abstractions
(即通用 NuGet程序包,所有使用MEL的项目都必须引用该程序包,因此可以保证该程序包可用)。
例如,如果您的服务实现需要非空的ILogger<T>
:
public interface IEncabulatorService
{
void Foo();
}
public class TurboEncabulatorService : IEncabulatorService
{
private readonly ILogger log;
public TurboEncabulatorService( ILogger<TurboEncabulatorService> log )
{
this.log = log ?? throw new ArgumentNullException(nameof(log));
}
public void Foo()
{
this.log.LogInformation( "Foo was invoked." );
}
}
然后,您可以使用NullLogger
虚拟记录器(例如,在单元测试项目中)实例化它,如下所示:
using Microsoft.Extensions.Logging; // This namespace must be imported because it uses extension-methods.
using Microsoft.Extensions.Logging.Abstractions;
[TestClass]
public class MyTests
{
[TestMethod]
public void TestEncabulator()
{
ILogger<TurboEncabulatorService> log = NullLoggerFactory.Instance.CreateLogger<TurboEncabulatorService>()
IEncabulatorService service = new TurboEncabulatorService( log );
}
}
如果您确实关心记录的内容,那么很遗憾,您确实需要实现自己的ILoggerFactory
(并记录到一些内部缓冲区),但是您无需提供您的记录。自己的CreateLogger<T>()
方法来创建强类型的ILogger<T>
实例,因为MEL库中作为扩展方法免费提供了该实例。
您在帖子中提到了“派生”类-因为如果您有这个...
public class BaseService
{
public BaseService( ILogger<BaseService> log )
{
// ...
}
}
public class DerivedService : BaseService
{
// ...?
}
...您可能想知道DerivedService
是否应该接受ILogger<BaseService>
或ILogger<DerivedService>
,因为肯定需要ILogger<BaseService>
才能传递给BaseService
,但是DerivedService
将失去其强类型类别名称。
...但事实并非如此!如果查看ILogger<T>
的定义,您会发现它是convariant generic interface because it has <out T>
rather than just <T>
。这意味着任何接受ILogger<Base>
的变量,方法或构造函数也将接受ILogger<Derived>
!
所以你有这个,这是完全合法的:
public class BaseService
{
public BaseService( ILogger<BaseService> log )
{
// ...
}
}
public class DerivedService : BaseService
{
public DerivedService( ILogger<DerivedService> log )
: base( log ) // `ILogger<BaseService>` can accept an `ILogger<DerivedService>`!
{
}
}
按照我之前的示例,您可以使用DerivedService
实例化BaseService
或NullLogger
的实例:
BaseService bs = new BaseService( NullLoggerFactory.Instance.CreateLogger<BaseService>() );
DerivedService ds = new DerivedService ( NullLoggerFactory.Instance.CreateLogger<DerivedService>() );
如果您发现自己需要频繁进行NullLogger
(或自己的ILogger
实现),则可以使用以下工厂帮助方法:
public static TService CreateServiceWithLogger<TService>( Func<ILogger<TService>,TService> ctor )
{
ILogger<TService> log = NullLoggerFactory.Instance.CreateLogger<TService>();
return ctor( log );
}
C#的类型推断规则将确保您不需要提供显式的TService
泛型参数类型参数,例如:
TurboEncabulatorService service = CreateServiceWithNullLogger( log => new TurboEncabulatorService( log ) );
答案 1 :(得分:0)
您应该使用依赖注入。
您的Controller
通过在其构造函数中引用接口来利用DI资源。对于ILogger<Class>
,这看起来像:
public class MyAwesomeController : Controller
{
private readonly ILogger _logger;
public MyAwesomeController(ILogger<MyAwesomeController> logger)
{
// logger contains a refference to the DIed ILogger
// We assign it to _logger so we can reference it from other
// methods in the class
_logger = logger;
}
public IActionResult GetIndex()
{
// Log something
//_logger.LogInformation();
return View();
}
}
您可以在文档中找到更多详细信息:Logging in ASP.NET Core