I am trying to use ServiceCollection
with Autofac populating the ServiceCollection
in a Console App. I read through the documentation but there is no guide for my specific scenario.
The issue I am facing is that built ServiceCollection does not find the implementation when I ask with interface type. I think AutoFac is not populating the ServieCollection
.
Program.cs
using System.Reflection;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Core.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
var serviceProvider = new ServiceCollection()
.AddLogging(cfg => cfg.AddConsole())
.Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information)
.AddAutofac(cfg =>
{
cfg.RegisterAssemblyTypes(Assembly.Load("Core")).AsImplementedInterfaces();
})
.BuildServiceProvider();
var markDownParser = serviceProvider.GetRequiredService<IMarkDownParser>();
MarkDownParser.cs
namespace Core;
public class MarkDownParser : IMarkDownParser
{
private readonly ILogger<MarkDownParser> _logger;
public MarkDownParser(ILogger<MarkDownParser> logger)
{
_logger = logger;
}
}
IMarkDownParser.cs
namespace Core.Interfaces;
public interface IMarkDownParser
{
object Parse(string text);
}
Error:
Unhandled exception. System.InvalidOperationException: No service for type 'Core.Interfaces.IMarkDownParser' has been registered.
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
at Program.<Main>$(String[] args) in /home/amir/RiderProjects/git-blog/ConsoleApp/Program.cs:line 20
CodePudding user response:
I think the problem is on AddAutofac
extension method only supports during ASP.NET Core 1.1 - 2.2.
This is not for ASP.NET Core 3 or the .NET Core 3 generic hosting support - ASP.NET Core 3 has deprecated the ability to return a service provider from ConfigureServices.
if we want to use autofac to be the DI Container, there is an example to talk about netcore quick-start
Once you've registered everything in the ServiceCollection and call Populate
to bring those registrations into Autofac by ContainerBuilder
Final, Creating a new AutofacServiceProvider
makes the DI container and we can use that.
var serviceCollection = new ServiceCollection()
.AddLogging(cfg => cfg.AddConsole())
.Configure<LoggerFilterOptions>(cfg => cfg.MinLevel = LogLevel.Information);
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(serviceCollection);
containerBuilder.RegisterAssemblyTypes(Assembly.Load("Core")).AsImplementedInterfaces();
var container = containerBuilder.Build();
var serviceProvider = new AutofacServiceProvider(container);
var markDownParser = serviceProvider.GetRequiredService<IMarkDownParser>();
CodePudding user response:
Documentation says that only use AddAutofac
ONLY FOR PRE-ASP.NET 3.0 HOSTING. THIS WON'T WORK FOR ASP.NET CORE 3.0 OR GENERIC HOSTING.
Since .net 6
has been tagged. I'm thinking the framework is part of the issue.
Here is my implementation as well as some documentation to help.
https://autofac.readthedocs.io/en/latest/integration/aspnetcore.html
// Main
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Reflection;
using IHost host = Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureContainer<ContainerBuilder>(builder =>
{
builder.RegisterAssemblyTypes(Assembly.Load("Core")).AsImplementedInterfaces();
})
.Build();
var markDownParser = host.Services.GetRequiredService<IMarkDownParser>();
Console.WriteLine(markDownParser);
// Core Assembly
using Microsoft.Extensions.Logging;
namespace Core
{
public interface IMarkDownParser
{
object Parse(string text);
}
public class MarkDownParser : IMarkDownParser
{
private readonly ILogger<MarkDownParser> _logger;
public MarkDownParser(ILogger<MarkDownParser> logger)
{
_logger = logger;
}
public object Parse(string text)
{
throw new NotImplementedException();
}
}
}