直截了当的问题是 :Microsoft.Extensions.Options.IOptions是否只能在伞形应用程序(在本例中为Web应用程序)或类库中使用?

例:

在一个n层的asp.net核心应用程序中,我们的服务层依赖于来自appsettings.json文件的一些设置。

我们刚开始的是Startup.cs中的这些内容:

  services.Configure<Services.Options.XOptions>(options =>
  {
    options.OptionProperty1 = Configuration["OptionXSection:OptionXProperty"];
  });

然后在服务构造函数中:

ServiceConstructor(IOptions<XOptions> xOptions){}

但是,假设在我们的服务层中,我们依赖于Microsoft.Extensions.Options

我们不确定这是推荐的方式还是有更好的做法?

我们的服务类库应该知道DI容器实现,这感觉有点尴尬。

===============>>#1 票数:5 已采纳

您也可以注册POCO设置进行注入,但是丢失了与appsettings.json编辑时相关的一些功能。

services.AddTransient<XOptions>(
    provider => provider.GetRequiredService<IOptionsSnapshot<XOptions>>().Value);

现在,当您在构造函数中注入XOptions时,您将获得该类。 但是当您编辑appsettings.json ,该值将不会更新,直到下次解决时,对于作用域服务将在下一个请求和单件服务永远不会

另一方面,注入IOptionsSnapshot<T> .Value将始终为您提供当前设置,即使重新加载appsettings.json (假设您使用.AddJsonFile("appsettings.json", reloadOnSave: true)注册它)。

保持功能无需将Microsoft.Extensions.Options包拉入服务/域层的明显原因是创建自己的界面和实现。

// in your shared service/domain assembly
public interface ISettingsSnapshot<T> where T : class
{
    T Value { get; }
}

并在应用程序端(服务/域程序集之外)实现它,即MyProject.Web (ASP.NET核心和组合根目录)

public class OptionsSnapshotWrapper<T> : ISettingsSnapshot<T>
{
    private readonly IOptionsSnapshot<T> snapshot;

    public OptionsSnapshotWrapper(IOptionsSnapshot<T> snapshot) 
    {
        this.snapshot = snapshot ?? throw new ArgumentNullException(nameof(snapshot));
    }

    public T Value => snapshot.Value;
}

并将其注册为

services.AddSingleton(typeof(ISettingsSnapshot<>), typeof(OptionsSnapshotWrapper<T>));

现在,您已从服务中删除了对IOptions<T>IOptionsSnapshot<T>的依赖性,但保留了它的所有优点,例如在编辑appsettings.json时更新选项。 更改DI时,只需将OptionsSnapshotWrapper<T>替换为新实现。

  ask by dee zg translate from so

未解决问题?本站智能推荐: