1
votes

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);
        }
1
normally associated with generic typesNkosi
I think you can also mock the logger, if need to inject in some service to resolve like var logger = Mock.Of<ILogger<SomeService>>(); var someService = new SomeService(logger);Ravi

1 Answers

2
votes

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:

  • Injecting ILogger<MyService> is equivalent to calling loggerFactory.CreateLogger<MyService>() or loggerFactory.CreateLogger("<namespace_of_my_service>.MyService")