简体   繁体   English

使 Autofac 解析非公共构造函数

[英]Make Autofac resolve non-public constructors

I´m using Autofac in my WPF application for dependency injection and can´t resolve this problem.我在我的 WPF 应用程序中使用 Autofac 进行依赖注入,但无法解决此问题。

I have created this abstract class ListItemViewModelBase from which two classes PasswordItemViewModel and CardItemViewModel inherits.我已经创建了这个抽象的 class ListItemViewModelBase两个类PasswordItemViewModelCardItemViewModel继承。

ListItemViewModelBase.cs ListItemViewModelBase.cs


    public abstract class ListItemViewModelBase
    {
        protected readonly IMessenger _messenger;
    
        public string Id { get; }
        public string Name { get; }
        public string Notes { get; }
    
        protected ListItemViewModelBase(IMessenger messenger, string id, string name, string notes)
        {
            _messenger = messenger;
    
            Id = id;
            Name = name;
            Notes = notes;
        }
    
        public abstract void SeeDetails();
    }

PasswordItemViewModel.cs PasswordItemViewModel.cs


    public partial class PasswordItemViewModel : ListItemViewModelBase
    {
        public string UserName { get; }
        public string Password { get; }
        public string Website { get; }
    
        public PasswordItemViewModel(IMessenger messenger, string id, string name, string userName, string password, string website, string notes) : base(messenger, id, name, notes)
        {
            UserName = userName;
            Password = password;
            Website = website;
        }
    
        [RelayCommand]
        public override void SeeDetails()
        {
            _messenger.Send(new PasswordDetailMessage(this));
        }
    }

CardItemViewModel.cs CardItemViewModel.cs


    public partial class CardItemViewModel : ListItemViewModelBase
    {    
        public string CardNumber { get; }
        public int ExpMonth { get; }
        public int ExpYear { get; }
    
        public CardItemViewModel(IMessenger messenger, string id, string name, string cardNumber, int expMonth, int expYear, string notes) : base(messenger, id, name, notes)
        {
            CardNumber = cardNumber;
            ExpMonth = expMonth;
            ExpYear = expYear;
        }
    
        [RelayCommand]
        public override void SeeDetails()
        {
            _messenger.Send(new CardDetailMessage(this));
        }
    }

My App.xaml.cs where the Autofac is configured looks like this:我的 App.xaml.cs 配置了 Autofac 如下所示:

App.xaml.cs App.xaml.cs


    public partial class App : Application
        {
            public static IServiceProvider ServiceProvider { get; private set; }
    
            [STAThread]
            public static void Main(string[] args)
            {
                using IHost host = CreateHostBuilder(args).Build();
    
                CreateGenericHost(host);
                InitAppAndRun();
            }
    
            private static void InitAppAndRun()
            {
                var app = new App();
                app.InitializeComponent();
                app.MainWindow = ServiceProvider.GetRequiredService();
                app.MainWindow!.Visibility = Visibility.Visible;
                app.Run();
            }
    
            #region Host builder
    
            private static IHostBuilder CreateHostBuilder(string[] args)
            {
                return Host.CreateDefaultBuilder(args)
                    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
                    .ConfigureServices(ConfigureServices)
                    .ConfigureContainer(ConfigureAutofacBuilder);
            }
    
            private static void ConfigureAutofacBuilder(HostBuilderContext ctx, ContainerBuilder builder)
            {
                builder.RegisterModule>();
                builder.RegisterModule>();
    
                var config = new ConfigurationBuilder();
                config.AddJsonFile("autofac.json");
    
                var module = new ConfigurationModule(config.Build());
                builder.RegisterModule(module);
            }
    
            private static void CreateGenericHost(IHost host)
            {
                host.Start();
                ServiceProvider = host.Services;
            }
    
            private static void ConfigureServices(HostBuilderContext ctx, IServiceCollection services)
            {
                services.AddSingleton();
            }
            #endregion
        }

When I try to start the application, program fails on using IHost host = CreateHostBuilder(args).Build();当我尝试启动应用程序时,程序无法using IHost host = CreateHostBuilder(args).Build(); and throws this error message:并抛出此错误消息:

Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'TestApp.Bases.ListItemViewModelBase'.'

Seems like Autofac can´t resolve non-public constructor of ListItemViewModelBase class.似乎 Autofac 无法解析ListItemViewModelBase class 的非公共构造函数。 Is there a way to make Autofac resolve these type of non-public constructors?有没有办法让 Autofac 解析这些类型的非公共构造函数?

Thanks, Tobias谢谢,托拜厄斯

Response to reply from Orenico:回复 Orenico 的回复:

Here is autofac.json which contains basically nothing.这是autofac.json基本上什么都不包含。


    {
      "modules": [],
      "components": []
    }

There are some typos in the sample code, like builder.RegisterModule>() , which won't compile and indicates there are registrations and other stuff going on that you're not showing us.示例代码中有一些拼写错误,例如builder.RegisterModule>() ,它不会编译并表明存在注册和其他您未向我们展示的内容。

However:然而:

You can't directly instantiate an abstract class.您不能直接实例化抽象 class。 Like, you can't do new ListItemViewModelBase .就像,你不能做new ListItemViewModelBase That means you can't register it.这意味着您无法注册它。 You can register derived classes As it, but even if Autofac could find the constructor you'd still hit a brick wall because it's not a concrete class.您可以注册派生类As it,但即使 Autofac 可以找到构造函数,您仍然会碰壁,因为它不是具体的 class。

If Autofac is resolving a type by reflection it doesn't go all the way down the chain looking at constructors, it only looks at the thing you're resolving.如果 Autofac 正在通过反射解析类型,它不会 go 一直查看构造函数,它只会查看您正在解析的内容。 That's why it sounds like you probably tried to register that abstract class.这就是为什么听起来你可能试图注册那个抽象的 class。

If I had to guess, you have some assembly scanning registrations in those modules you're not showing us where you try registering all the view models and you didn't exclude the base class from the registrations.如果我不得不猜测,您在那些模块中有一些装配扫描注册,您没有向我们展示您尝试注册所有视图模型的位置,并且您没有从注册中排除基本 class。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM