在 Simple Injector 中注册具体类型并使用它会抛出 ActivationException

Registering a concrete type in Simple Injector and using it throws ActivationException

我正在使用 Simple Injector 在 .NET Core 控制台应用程序的容器中注册具体类型(在 Program.cs 中),但是 Simple Injector 在启动时抛出异常:

The constructor of type Application contains the parameter with name 'configUpdater' and type ConfigUpdater, but ConfigUpdater is not registered. For ConfigUpdater to be resolved, it must be registered in the container. An implicit registration could not be made because Container.Options.ResolveUnregisteredConcreteTypes is set to 'false', which is now the default setting in v5. This disallows the container to construct this unregistered concrete type. For more information on why resolving unregistered concrete types is now disallowed by default, and what possible fixes you can apply, see https://simpleinjector.org/ructd

编辑: 添加抛出异常的 MRE 示例:

using System.Threading.Tasks;
using NLog;
using SimpleInjector;

namespace MRE
{
    public static class Program
    {
        private static Container container;

        static Program()
        {
            container = new Container();

            container.Register<IApplication, Application>(Lifestyle.Singleton);
            var appSettings = new AppSettings();

            container.Register(
                typeof(AppSettings),
                () => appSettings,
                Lifestyle.Singleton
            );

            container.RegisterConditional(
                typeof(ILog),
                typeCtx => typeof(NLogProxy<>).MakeGenericType(typeCtx.Consumer.ImplementationType),
                Lifestyle.Singleton,
                predCtx => true
            );

            container.Register<IConfigUpdater, ConfigUpdater>(Lifestyle.Scoped);
        }

        public static void Main(string[] args)
        {
            var application = container.GetInstance<IApplication>();
            application.RunAsync();
        }
    }

    public class AppSettings
    {
        public string ConnectionString { get; set; } = "DataSource=data.db";
    }

    public interface ILog
    {
        void Info(string message);
    }

    public class NLogProxy<T> : ILog
    {
        private static readonly NLog.ILogger Logger = LogManager.GetLogger(typeof(T).FullName);

        public void Info(string message) => Logger.Log(LogLevel.Info, message);
    }

    public interface IApplication
    {
        Task RunAsync();
    }

    public class Application : IApplication
    {
        private readonly ILog logger;
        private readonly IConfigUpdater configUpdater;

        public Application(
            ILog logger,
            IConfigUpdater configUpdater
        )
        {
            this.logger = logger;
            this.configUpdater = configUpdater;
        }

        public Task RunAsync()
        {
            logger.Info("Running");
            configUpdater.DoTask();
            return Task.CompletedTask;
        }
    }

    public interface IConfigUpdater
    {
        Task DoTask();
    }

    public class ConfigUpdater : IConfigUpdater
    {
        private readonly AppSettings appSettings;
        private readonly ILog logger;

        public ConfigUpdater(
            AppSettings appSettings,
            ILog logger
        )
        {
            this.appSettings = appSettings;
            this.logger = logger;
        }

        public Task DoTask()
        {
            var connectionString = appSettings.ConnectionString;
            logger.Info(connectionString);
            return Task.CompletedTask;
        }
    }
}

编辑#2: 在 MRE 的帮助下,我发现我的问题实际上隐藏在幕后。这是使用 Lifestyle.Scoped 的问题,由于某种原因它不是第一个抛出的异常。将默认生活方式设置为 AsyncScopedLifestyle 修复它。

在 MRE 的帮助下,我发现实际错误与默认的 Lifestyle SimpleInjector 正在使用有关。添加行:

container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();

解决了这个问题。

至于为什么没有先抛出Lifestyle异常,我不知道。