Autofac maui,Autofac.Core.Activators.Reflection.NoConstructorsFoundException:'找不到类型 'xxx.Resource+Xml' 的可访问构造函数

Autofac maui, Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'xxx.Resource+Xml'

所以我正在学习 xamarin 表单的课程,但我正在调整它以用于 .net Maui。到目前为止,这是一个基本的应用程序,仅构建了弹出窗口 shell。

作者正在使用我以前从未听说过或使用过的autofac。我按照示例进行操作并得到 运行time 异常:

Autofac.Core.Activators.Reflection.NoConstructorsFoundException:“未找到 'MauiApp4.Resource+Xml' 类型的可访问构造函数。”

我不知道这意味着什么,也不知道如何继续:叹息

(我认为它试图说它无法访问某些东西?我也怀疑与 IContainer 有关?)

哦哦

当我尝试在来自 Visual Studio 2022 社区版的 Android Pixel 5.0 API 30 Android 模拟器上构建和 运行 应用程序时会发生这种情况.

它似乎在 Container = builder.Build();

行崩溃

Autofac 使用 nuget 加载,版本为 6.3.0

我不知道我使用的是哪个版本的 .net 或 maui,但它是最新的(我如何获得此信息?)

这是当前的(适用的?)代码:(它也在我的 github 存储库 https://github.com/gfmoore/MauiApp4B.App/tree/master 中)

App.xaml.cs

using System.Reflection;
using Autofac;
using IContainer = Autofac.IContainer;

namespace MauiApp4;

public partial class App : Application
{
    public static IContainer Container;

    public App()
    {
      InitializeComponent();
      //class used for registration
      var builder = new ContainerBuilder();

      //scan and register all classes in the assembly
      var dataAccess = Assembly.GetExecutingAssembly();
      builder.RegisterAssemblyTypes(dataAccess)
             .AsImplementedInterfaces()
             .AsSelf();

      //TODO - register repositories if you use them
      //builder.RegisterType<Repository<User>>().As<IRepository<User>>();

      //get container
      Container = builder.Build();

      //set first page
      MainPage = new AppShell();
    }
}

AppShell.xaml.cs

using Autofac;

namespace MauiApp4;

public partial class AppShell : Shell
{
  public AppShell()
  {
    InitializeComponent();
    Application.Current.UserAppTheme = AppTheme.Dark;
    BindingContext = App.Container.Resolve<AppShellViewModel>();
  }
}

AppShellViewModel.cs

using System;
using System.Windows.Input;

namespace MauiApp4
{
  public class AppShellViewModel
  {
    public ICommand SignOutCommand { get => new Command(async () => await SignOut());  }

    private async Task SignOut()
    {
      await Shell.Current.DisplayAlert("Todo sign out code", "You have been logged out.", "Ok");
    }
  }
}

感谢收到的任何帮助。

G

欢迎来到依赖注入和本机代码的奇妙世界。跳入游泳池有点深,所以你要对自己有耐心,咬紧指关节,并与 Google/Bing/whatever 成为最好的朋友。

我不是 MAUI 用户,但我是 Autofac 的所有者之一。 Autofac 是一个依赖注入/控制反转框架,这意味着它将找到您所有的依赖项并将它们连接起来。您无需调用 new X(y, z) 来创建内容,而是从控制反转容器中获取内容。容器将为您的构造函数找出参数并全部解析它们。

There is a lot of Autofac documentation here. 很多。 DI 可能是一个复杂的主题,涉及确定对象应该存在多长时间(它们是单例还是您每次请求时都想要一个新的?)以及如何连接起来。这个文档将是一个好朋友,就像你最喜欢的搜索引擎一样。

综合起来,我在你的代码中看到了这一点:

builder.RegisterAssemblyTypes(dataAccess)
       .AsImplementedInterfaces()
       .AsSelf();

这是在 assembly scanning 将数据访问程序集 中的每种类型 注册到容器中。通过这样做,您告诉 Autofac 您还打算 每次在该数据访问程序集 中按字面意义解析,因此当您要求它时,它会尝试定位构造函数并开始new-ing 搞定了。

你的错误是:

Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'MauiApp4.Resource+Xml'.'

...但是您没有提供堆栈跟踪。我不记得 Autofac 在容器构建时对构造函数进行了任何扫描,并且该异常来自激活器(意味着它正在尝试解决该问题),所以我 猜测 爆炸的实际行是这样的:

BindingContext = App.Container.Resolve<AppShellViewModel>();

也就是试图解决某事的那一行。 我不确定,因为它很可能是 MAUI 内部的东西! 就像我说的,我不是 MAUI 用户,所以我猜,你不是包括堆栈跟踪,所以我所能做的就是猜测更多。

不过,将所有这些放在一起,似乎 某些东西 正在尝试解析 MauiApp4.Resource+Xml 的一个实例(一个 class 称为 Xml它嵌套在 class MauiApp4.Resource?) 中并且没有 public 构造函数,因此 Autofac 无法为您“更新”。这可能与以下事实有关:从字面上看,程序集中的每个类型 都已注册。

我强烈建议只注册您需要的类型,并且只注册您使用的接口。使用 AsImplementedInterfacesAsSelf 进行大量注册是 容易 但它也会使故障排除变得更加困难,因为这可能发生在某些解析链中. 我不能保证更改程序集扫描会解决这个问题,它可能会让问题更容易解决。

第一步是弄清楚正在使用什么 MauiApp4.Resource+Xml 以及为什么要创建它。比如,找到一个带有构造函数参数的 class。它可能嵌套在解析链的深处!可能是compiler-generated! 完整异常 - 带有内部异常消息和堆栈跟踪 - 可能对您有所帮助!

// Some class may need a Resource...
public class SomeClassInTheApp
{
  public SomeClassInTheApp(Maui.Resource resource) { ... }
}
// And the resource may need the internal class?
public class Resource
{
  public Resource(Xml xml) {...}

  // I imagine Xml is nested inside Resource?
  public Xml
  {
    // But it might not have a public constructor
    internal Xml(){}
  }
}

有很多我只能猜测,但希望这能给你一个地方去看看。

我会说,一定要阅读整个异常,包括内部异常消息和堆栈跟踪。它们可能很长,并且可能令人困惑,但 Autofac 已尽力尝试在其中提供足够的信息以指出问题所在。缺点是,由于问题可能在堆栈的某个地方很深,异常可能需要一些阅读才能解决。

There's a whole debugging and troubleshooting tips page in the Autofac docs 这也可能有帮助。

抱歉,我无法告诉您确切要修复的内容,但希望这能解开您的障碍,让您找到正确的位置。

令人高兴的是,尽管这是 Xamarin 表单课程而不是 Maui 课程,但课程的讲师做出了回应。他的解决方案似乎符合上面非常详细和精彩的答案。

删除代码:

builder.RegisterAssemblyTypes(dataAccess)
       .AsImplementedInterfaces()
       .AsSelf();

并手动添加您的注册?所以你加一行:

builder.RegisterType<AppShellViewModel>();

这样应用程序就可以运行了。

再次感谢 Travis Illig。我认为当人们花这么多时间以如此详细的方式帮助他人时,这真是太棒了。 :)