【问题标题】:Options pattern, configuration, in Legacy .NET Application with Simple Injector带有简单注入器的旧 .NET 应用程序中的选项模式、配置
【发布时间】:2018-11-08 17:37:55
【问题描述】:

这篇文章,https://medium.com/@dmitryzaets/legacy-net-applications-configuration-management-net-framework-4-5-1-68220335d9d8,描述了如何将选项模式与 Autofac 一起使用。我试图将其翻译为与 Simple Injector 一起使用。但我没有运气。 这是我的国际奥委会代码

public class IocBootstrap2
{
    private Container Container { get; }
    public IocBootstrap2()
    {
        Container = new Container();
        var configurationBuilder = new ConfigurationBuilder()
            .SetBasePath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Configuration"))
            .AddJsonFile("settings.json", optional: false, reloadOnChange: true);
        var configuration = configurationBuilder.Build();
        //Register Options
        Container.Register(typeof(IOptions<>), typeof(OptionsManager<>));
        Container.Register(typeof(IOptionsMonitor<>), typeof(OptionsMonitor<>));
        Container.Register(typeof(IOptionsFactory<>), typeof(OptionsFactory<>));
        Container.Register(typeof(IOptionsMonitorCache<>), typeof(OptionsCache<>));
        // Register ConfigurationOptions
        Container.RegisterConfigurationOptions2<MailingOptions>(configuration.GetSection("mailing"));

    #if DEBUG
        Container.Verify();
    #endif   
 }
}

public static class ConfigurationSetupExtensions2
{
    public static void RegisterConfigurationOptions2<TOptions>(this Container container, IConfiguration config)
        where TOptions : class
    {
        container.Register(typeof(IOptionsChangeTokenSource<TOptions>),
            () => new ConfigurationChangeTokenSource<TOptions>(config), Lifestyle.Transient);
        container.Register(typeof(IConfigureOptions<TOptions>),
            () => new ConfigureFromConfigurationOptions<TOptions>(config), Lifestyle.Transient);
    }
}
 public class MailingOptions
{
    public MailingOptions()
    {
        BatchSize = 1;
    }
    public int BatchSize { get; set; }
    public int BatchDelay { get; set; }
}

settings.json

{
  "mailing": {
    "batchSize": 15, 
    "batchDelay": 1
  }
}

然后我将它注入到这样的 ViewModel:s 构造函数中

  public class BlockViewModel 
    {
        private readonly MailingOptions _options;

        #region Constructor
        public BlockViewModel(IOptions<MailingOptions> options) 
        {
            _options = options.Value;
        }
        #endregion

    }

当我运行它时,Container.Verify 中出现异常。

OptionsFactory 类型的构造函数包含名称为“setups”且类型为 IEnumerable> 的参数,该参数未注册。请确保 IEnumerable> 已注册,或更改 OptionsFactory 的构造函数。但是,有 IConfigureOptions 的注册;您的意思是依赖 IConfigureOptions

堆栈跟踪:

在 SimpleInjector.Container.ThrowParameterTypeMustBeRegistered(InjectionTargetInfo 目标)

如何注册IEnumerable&lt;IConfigureOptions&lt;MailingOptions&gt;&gt;? 谁能告诉我我做错了什么,或者更准确地说,我不明白什么?

【问题讨论】:

    标签: configuration simple-injector configurationmanager legacy-code .net-core-configuration


    【解决方案1】:

    简短的回答是:不要将IOptions&lt;T&gt; 注入您的应用程序组件中。正如here 所解释的那样,这只会使您的组件、它们的单元测试以及您已经注意到的配置复杂化。

    相反,让BlockViewModel 直接依赖于MailingOptions

    public class BlockViewModel 
    {
        private readonly MailingOptions _options;
    
        public BlockViewModel(MailingOptions options) 
        {
            _options = options ?? throw new ArgumentNullException(nameof(options));
        }
    }
    

    这使您可以将配置简化为以下内容:

    Container = new Container();
    var configutation = new ConfigurationBuilder()
      .SetBasePath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Configuration"))
        .AddJsonFile("settings.json", optional: false);
        .Build();
    
    MailingOptions options = configuration.GetSection("mailing").Get<MailingOptions>();
    Container.RegisterInstance<MailingOptions>(options);
    
    // Register View Models
    Container.Register<BlockViewModel>();
    
    Container.Verify();
    

    【讨论】:

    • 这个答案需要注意的一点:当您注册 MailingOptions 时,它将被注册为单例。因此,在显式更新注册(通常通过重新启动应用程序)之前,它的值不会改变。解决此问题的一种方法是执行 RegisterFactory(() =&gt; configuration.GetSection("mailing").Get&lt;MailingOptions&gt;()); 之类的操作 - 如果您这样做,则每次都会重新检索配置。通常这不是必需的(而且速度较慢)。但是,如果您希望能够在不重新启动应用程序的情况下即时更新配置,则需要考虑。
    • @JED,对于无需重启的更新很重要的特定场景,IOptionSnapshot&lt;T&gt; 模型更适合。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    相关资源
    最近更新 更多