IConfigureOptions <t>未创建作用域选项

时间:2018-02-21 20:04:32

标签: .net-core asp.net-core-2.0 asp.net-core-webapi coreclr

通常Options是单身人士。但是我正在从数据库构建选项,其中一个Options属性是密码,每个月都在不断更改。所以我想创建选项的Scoped实例。我正在使用下面的IConfigureOptions<T>来构建数据库中的选项

public class MyOptions
{
   public string UserID {get;set;}
   public string Password {get;set;
}

public class ConfigureMyOptions : IConfigureOptions<MyOptions>
{
    private readonly IServiceScopeFactory _serviceScopeFactory;
    public ConfigureMyOptions(IServiceScopeFactory serviceScopeFactory)
    {
        _serviceScopeFactory = serviceScopeFactory;
    }

    public void Configure(MyOptions options)
    {
        using (var scope = _serviceScopeFactory.CreateScope())
        {
            var provider = scope.ServiceProvider;
            using (var dbContext = provider.GetRequiredService<MyDBContext>())
            {
                options.Configuration = dbContext.MyOptions
                                        .SingleOrDefault()
                                        .Select(x => new MyOptions()
                                        {
                                            UserID = x.UserID,
                                            Password = x.Password
                                        });
            }
        }
    }
}

在控制器中使用它

    public class HomeController : BaseController
    {
        private readonly MyOptions _options;
        public HomeController(IOptions<MyOptions> option)
        {
            _options = option.Value;
        }

        [HttpGet]
        [Route("home/getvalue")]
        public string GetValue()
        {
            // do something with _options here
            return "Success";
        }
    }

我想为每个新请求创建一个MyOptions实例,所以在startup.cs中将其注册为Scoped

services.AddScoped<IConfigureOptions<MyOptions>, ConfigureMyOptions>();

但是,当我将调试器放在ConfigureMyOptions的Configure方法中时,它只会在第一个请求中被点击一次。对于下一个请求,容器返回相同的实例(如单例)。

如何在此处设置范围,以便为每个请求创建MyOptions?

1 个答案:

答案 0 :(得分:3)

在您的控制器中使用IOptionsSnapshot代替IOptions,它会为每个请求重新创建选项。

为什么不与IOptions合作:

配置API的

.AddOptions扩展方法将OptionsManager实例注册为IOptions<>

的单人游戏
services.TryAdd(ServiceDescriptor.Singleton(typeof(IOptions<>), typeof(OptionsManager<>)));
services.TryAdd(ServiceDescriptor.Scoped(typeof(IOptionsSnapshot<>), typeof(OptionsManager<>)));

OptionsManageruses caching internally

 public virtual TOptions Get(string name)
 {
     name = name ?? Options.DefaultName;

     // Store the options in our instance cache
     return _cache.GetOrAdd(name, () => _factory.Create(name));
 }

github上的以下问题有助于找到上述内容:OptionsSnapshot should always be recreated per request