如何将 AutoFac 与 .NET MAUI 结合使用

Ste*_*ork 6 autofac autofac-module .net-6.0 .net-maui

几年前,我创建了一套用于 CQRS 的 nuget 包,它使用 AutoFac 模块来连接内部结构。我想在我的 .NET MAUI 开发中使用它,因此我已将它们更新到 .NET 6.0,并且它们很好地链接到我的 MAUI 项目,但我不确定我的注册中缺少什么。我的框架的 AutoFac 模块注册了一个 IDateTimeService,但是当我将其添加到注册类的构造函数中时,它无法解析。

因此,按照 .NET Core 的 AutoFac 指南,我添加了 Populate 调用,然后加载 AutoFac 模块。

using Autofac;
using Autofac.Extensions.DependencyInjection;
using Pages;
using Perigee.Framework.Services;
using Services;
using ViewModels;


public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
        
        builder.Services.AddSingleton<IAppNavigationService, AppNavigationService>();
        
        builder.Services.AddSingleton<AppShellViewModel>();
        builder.Services.AddTransient<MainPageViewModel>();

        builder.Services.AddSingleton<AppShell>();
        builder.Services.AddSingleton<MainPage>();
        

        // Hook in AutoFac for the PerigeeFramework services
        var autofacBuilder = new ContainerBuilder();
        autofacBuilder.Populate(builder.Services);

        autofacBuilder.RegisterModule(new ServicesModule());
        autofacBuilder.Build(); // Invokes the Load method on the registered Modules.


        return builder.Build();
    }
}
Run Code Online (Sandbox Code Playgroud)

AutoFac 模块的启动方式如下:

    public class ServicesModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.Register(c =>
            {
                var config = c.IsRegistered<IDateTimeConfig>() ? c.Resolve<IDateTimeConfig>() : null;
                return new DateTimeService(config);
            }).As<IDateTimeService>().InstancePerLifetimeScope();
Run Code Online (Sandbox Code Playgroud)

这是 AppShellViewModel 的定义

    public AppShellViewModel(IDateTimeService dateTimeService)
Run Code Online (Sandbox Code Playgroud)

它被注入到AppShell中:

public partial class AppShell : Shell
{
    public AppShell(AppShellViewModel viewModel)
    {
        InitializeComponent();

        BindingContext = viewModel;
Run Code Online (Sandbox Code Playgroud)

在运行时IDateTimeService无法解决。我也尝试过仅在没有模块的情况下注册 AutoFac,但它无法解决:

        // Hook in AutoFac for the PerigeeFramework services
        var autofacBuilder = new ContainerBuilder();
        autofacBuilder.Populate(builder.Services);

        autofacBuilder.RegisterType<DateTimeService>().As<IDateTimeService>().SingleInstance();
        
        var cont = autofacBuilder.Build();


        return builder.Build();
    }
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

我需要 .NET DI 以外的东西的关键原因是因为该架构利用了装饰器,SimpleInjector 和 AutfoFac 提供了开箱即用的装饰器,所以我选择了 AutoFac。无论哪种情况,我都需要使用这种“交叉线”方法来使用 AutoFac 和 .NET DI,因为 MAUI 使用的是内置方法。有谁知道我缺少哪一步来阻止 AutoFac 模块的注册出现在 IServiceCollection 中,或者我可以在 MauiApp 上用 AutoFac 完全替换 .NET DI 吗?

编辑:我已经整理了我的应用程序的精简版本。我想也许我需要将一个新的 AutoFacServiceProvider 传递给应用程序,并且 ISomeService 在向 AutoFac 注册时确实会解析 在此输入图像描述

MainPage = serviceProvider.GetService<AppShell>()但是,如果我尝试将 ISomeService 注入另一个注册类,则调用无法解析。如果该服务已使用标准 DI 注册,它将可以正常工作。

有人知道如何宣传 AutoFac 服务提供商作为毛伊岛将使用的服务提供商吗?项目在这里

Bet*_*tic 4

MauiAppBuilder从 调用)有一个名为ConfigureContainerMauiProgram的方法,它需要Autofac 提供的一个工厂,并且可以选择它可以接受一个委托,您可以在其中定义您的配置。IServiceProviderAutofacServiceProviderFactoryAction<ContainerBuilder>

在你的情况下,可能看起来像这样:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            })
            .ConfigureContainer(new AutofacServiceProviderFactory(), autofacBuilder => {
                // Registrations
                // Don't call the autofacBuilder.Build() here - it is called behind the scenes
            });

        return builder.Build();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @AkshayKumar - 我不知道是否有办法直接访问容器。但如果只需要获取任何已注册的组件 - 您可以将 IServiceProvider 作为项目的任何构造函数中的依赖项。(它将得到解决)使用它,您可以调用 GetService&lt;YourComponentType&gt;() 来访问任何已注册的组件。示例: YourComponentConstructor(IServiceProviderprovider) { var yourComponent =provider.GetService&lt;YourComponentType&gt;() } (3认同)