.net 核心,n 层应用程序,如果服务层依赖于 Microsoft.Extensions.Options.dll [英] .net core, n-layered app, should services layer have dependency on Microsoft.Extensions.Options.dll

查看:27
本文介绍了.net 核心,n 层应用程序,如果服务层依赖于 Microsoft.Extensions.Options.dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

直截了当的问题是:Microsoft.Extensions.Options.IOptions 是仅在伞形应用(在本例中为 Web 应用)的上下文中还是在类库中使用?

Straightforward question is: are Microsoft.Extensions.Options.IOptions meant to be used only within the context of umbrella app (web app in this case) or in class libraries also?

示例:

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

In a n-layered, asp.net core app we have services layer that is dependant on some settings coming from appsettings.json file.

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

What we first started with is something along these lines in Startup.cs:

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

然后在服务构造函数中:

And then in service constructor:

ServiceConstructor(IOptions<XOptions> xOptions){}

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

But that assumes that in our Service layer we have dependecy on Microsoft.Extensions.Options.

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

We're not sure if this is recomended way or is there some better practice?

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

It just feels a bit awkward our services class library should be aware of DI container implementation.

推荐答案

您也可以注册用于注入的 POCO 设置,但是您会丢失一些与 appsettings.json 被编辑时相关的功能.

You can register POCO settings for injection too, but you lose some functionalities related to when the appsettings.json gets edited.

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

现在,当您在构造函数中注入 XOptions 时,您将获得该类.但是,当您编辑 appsettings.json 时,该值将不会更新,直到下一次解决该值时,范围服务将在下一次请求中出现,而单例服务从不.

Now when you inject XOptions in constructor, you will get the class. But when your edit your appsettings.json, the value won't be updated until the next time it's resolved which for scoped services would be on next request and singleton services never.

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

On other side injecting IOptionsSnapshot<T> .Value will always get you the current settings, even when appsettings.json is reloaded (assuming you registered it with .AddJsonFile("appsettings.json", reloadOnSave: true)).

保留功能而无需将 Microsoft.Extensions.Options 包拉入您的服务/域层的显而易见的原因是创建您自己的接口和实现.

The obvious reason to keep the functionality w/o pulling Microsoft.Extensions.Options package into your service/domain layer will be create your own interface and implementation.

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

并在应用程序端(在您的服务/域程序集之外)实现它,即 MyProject.Web(ASP.NET Core 和组合根所在的位置)

and implement it on the application side (outside of your services/domain assemblies), i.e. MyProject.Web (where ASP.NET Core and the composition root is)

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>));

现在您已经从您的服务中删除了对 IOptionsIOptionsSnapshot 的依赖,但保留了它的所有优势,例如在 appsettings.json 时更新选项被编辑.当您更改 DI 时,只需将 OptionsSnapshotWrapper 替换为您的新实现即可.

Now you have removed your dependency on IOptions<T> and IOptionsSnapshot<T> from your services but retain all up advantages of it like updating options when appsettings.json is edited. When you change DI, just replace OptionsSnapshotWrapper<T> with your new implementation.

这篇关于.net 核心,n 层应用程序,如果服务层依赖于 Microsoft.Extensions.Options.dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆