【问题标题】:.net core, n-layered app, should services layer have dependency on Microsoft.Extensions.Options.dll.net 核心,n 层应用程序,服务层是否应该依赖 Microsoft.Extensions.Options.dll
【发布时间】:2017-07-08 15:13:50
【问题描述】:

直截了当的问题是: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 容器实现,这感觉有点尴尬。

【问题讨论】:

  • 在我认为有用的地方使用 IOptions 是完全合法的
  • 如果您明天想在其他使用 .net 核心默认容器以外的 DI 容器的伞式应用程序中使用您的服务,会发生什么情况?
  • 服务类不需要知道DI,它只是有一个consturcotr依赖,服务本身也应该由未更新的DI添加。 DI 贯穿所有层
  • 除 Startup.cs 外,您的所有类都不应知道 DI 容器,在该容器中,您可以轻松切换到其他 DI 容器,而不是默认容器。拥有构造函数依赖并不意味着意识到 DI
  • @deezg in 99.9% 我不需要重新加载appsettings.json,所以我不使用IOptions&lt;T&gt;。您可以在这里找到关于这种方法的优缺点的类似问题:stackoverflow.com/questions/43679665/…

标签: configuration asp.net-core .net-core


【解决方案1】:

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

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

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

另一方面,注入IOptionsSnapshot&lt;T&gt; .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 Core 和组合根所在的位置)

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&lt;T&gt;IOptionsSnapshot&lt;T&gt; 的依赖,但保留了它的所有优点,例如在编辑 appsettings.json 时更新选项。当您更改 DI 时,只需将 OptionsSnapshotWrapper&lt;T&gt; 替换为您的新实现即可。

【讨论】:

    猜你喜欢
    • 2020-01-17
    • 2010-10-03
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 2013-08-03
    • 2011-03-01
    相关资源
    最近更新 更多