使用Autofac在.NET 6控制台应用程序和ServiceCollection中。

7

我正在尝试在控制台应用程序中使用ServiceCollection和Autofac,填充ServiceCollection。我阅读了文档,但没有适用于我的具体情况的指南。

我面临的问题是,当我使用接口类型询问时,构建的ServiceCollection找不到实现。我认为AutoFac没有填充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);
}

错误:

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

IMarkDownParserMarkDownParser的命名空间是什么? - D-Shih
@D-Shih更新了问题。 - Node.JS
2个回答

4
我认为问题出在 AddAutofac 扩展方法只支持 ASP.NET Core 1.1 - 2.2

这不适用于 ASP.NET Core 3+ 或 .NET Core 3+ 的通用主机支持,ASP.NET Core 3 已弃用从 ConfigureServices 返回服务提供程序的功能。

如果我们想要使用 Autofac 作为 DI 容器,这里有一个讲解 netcore 快速入门 的示例。

一旦您在 ServiceCollection 中注册了所有内容并通过 ContainerBuilder 调用 Populate 将这些注册带入 Autofac 中,

最后,创建一个新的 AutofacServiceProvider 来创建 DI 容器,我们就可以使用它了。

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>();

1
文档表示仅适用于AddAutofac
仅适用于ASP.NET 3.0之前的主机。这对于ASP.NET CORE 3.0+或通用主机不起作用。

由于.net 6已经被标记,我认为框架是问题的一部分。

以下是我的实现以及一些有用的文档:
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);

// 核心程序集

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();
        }
    }
}

在这种情况下,单元测试怎么办?在我看来,这种用例中没有主机。 - Karel Kral

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接