Reputation: 601
I'm working with a .Net Core 3.1 XUnit project.
I create a SerivceCollection and call the AddLogging extension method. Then I can create an ILogger instance with the LoggerFactory / ILoggerFactory and when I debug, I can my ServiceCollection has a ServiceDescriptor for this type:
Lifetime = Singleton, ServiceType = {Name = "ILogger`1" FullName = "Microsoft.Extensions.Logging.ILogger`1"}, ImplementationType = {Name = "Logger`1" FullName = "Microsoft.Extensions.Logging.Logger`1"}
I'm curious what that tick mark means in the type name and if it's possible to resolve an ILogger instance without using the LoggerFactory.
Here are a couple failed attempts at resolving ILogger`1. The last call to CreateLogger works.
[Fact]
public void AddLogging_RegistersILogger()
{
var services = new ServiceCollection().AddLogging();
var serviceProvider = services.BuildServiceProvider();
var logger1 = serviceProvider.GetService<ILogger>(); // logger == null
try
{
var logger2 = serviceProvider.GetService(typeof(ILogger<>));
}
catch (Exception e)
{
// Implementation type 'Microsoft.Extensions.Logging.Logger`1[T]' can't be converted to service type 'Microsoft.Extensions.Logging.ILogger`1[TCategoryName]'
}
try
{
var loggerTypes = Assembly.GetAssembly(typeof(ILogger)).GetTypes().Where(t => t.Name == "ILogger`1");
var loggerType = loggerTypes.First();
var logger3 = serviceProvider.GetService(loggerType);
}
catch(Exception e)
{
// Implementation type 'Microsoft.Extensions.Logging.Logger`1[T]' can't be converted to service type 'Microsoft.Extensions.Logging.ILogger`1[TCategoryName]'
}
var logger4 = serviceProvider.GetService<ILoggerFactory>().CreateLogger<DependencyInjectionTests>();
Assert.NotNull(logger4);
}
Upvotes: 4
Views: 6679
Reputation: 4243
I resolved the problem by implemented NLog using the following steps in asp.net core
https://code-maze.com/net-core-web-development-part3/
Nuget:
1. NLog.Config
2. NLog.Extensions.Logging
Logging
functionality added to software so someone can get insight into the software
Logging as targets and rules.
nlog.config (change property to copy always)
1. the logfile name creates a file in the logs directory
2. debug is wrote to the logfile target
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Trace"
internalLogFile="internallog.txt">
<targets>
<target name="logfile" xsi:type="File"
fileName="${startupdir}\logs\${shortdate}_logfile.txt"
layout="${longdate} ${level:uppercase=true} ${message}"/>
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="logfile" />
</rules>
</nlog>
startup.cs
1. load the nlog.config
2. ConfigureLoggerService is part of the static class called Service Extensions. Its job is to create a singleton task for the LoggerManager
public Startup(IConfiguration configuration)
{
LogManager.LoadConfiguration(@"nlog.config");
Configuration = configuration;
//_env = env;
}
public void ConfigureServices(IServiceCollection services)
{
services.ConfigureLoggerService();
}
serviceExtensions.cs
public static class ServiceExtensions
{
public static void ConfigureLoggerService(this IServiceCollection services)
{
services.AddSingleton<ILoggerManager, LoggerManager>();
}
}
LoggerManager.cs
1. use the dependency injected Logger for nLog to post based on type.
public class LoggerManager : ILoggerManager
{
private static ILogger logger = LogManager.GetCurrentClassLogger();
public void LogDebug(string message)
{
logger.Debug(message);
}
public void LogError(string message)
{
logger.Error(message);
}
public void LogInfo(string message)
{
logger.Info(message);
}
public void LogWarn(string message)
{
logger.Warn(message);
}
}
Upvotes: 0
Reputation: 1016
The tick on "ILogger`1"
means its a generic type, i.e. ILogger<CategoryName>
You can inject ILogger<T>
for any generic type. The generic type is used to set the category name in a convenient manner, e.g. ILogger<Controller>
will have "Microsoft.AspNetCore.Mvc.Controller"
category name
The common practice is for each class to have a logger with the category name of the class, e.g. a class namedMyService
will have a logger ILogger<MyService>
You can either inject ILogger<T>
or use ILoggerFactory
:
ILogger<MyService>
is equivalent to calling loggerFactory.CreateLogger<MyService>()
or loggerFactory.CreateLogger("<namespace_of_my_service>.MyService")
Upvotes: 4