Asp.net core URL重写依赖于配置依赖项注入/作用域服务的中间件。网芯

Asp.net core URL重写依赖于配置依赖项注入/作用域服务的中间件。网芯,asp.net-core,dependency-injection,app-startup,Asp.net Core,Dependency Injection,App Startup,使用重写规则类处理依赖项注入/作用域服务有点困难 我有一个重定向类,它实现了IRule class ActivateRedirects : IRule { public void ApplyRule(RewriteContext context) { // Do stuff here which relies on CoreSettings (info below) } } 我还有一个CoreSettings类,它包含各种设置,其中一些设

使用重写规则类处理依赖项注入/作用域服务有点困难

我有一个重定向类,它实现了
IRule

class ActivateRedirects : IRule
{        
    public void ApplyRule(RewriteContext context)
    {
        // Do stuff here which relies on CoreSettings (info below)
    }
}
我还有一个
CoreSettings
类,它包含各种设置,其中一些设置是
ApplyRule
工作所必需的,它在
startup.cs
中初始化如下

var configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "site.json"), optional: false, reloadOnChange: true);
IConfigurationRoot root = configurationBuilder.Build();             
CoreSettings s = new CoreSettings();  
services.Configure<CoreSettings>(root.GetSection("Website"));
我已经读了好几页关于为什么我不能简单地将DI添加到
ActivateDirections
类,或者在使用
app.ApplicationServices.GetRequiredService
时显式传递值的内容,但是我读到的所有内容都告诉我不能做什么,我找不到任何东西告诉我可以做什么


在我被告知重写代码以不需要
CoreSettings
进行重写之前,我不能这样做,因为其中一个重写规则取决于远程服务器通过
REST API
设置的条件,而
CoreSettings
类中需要的是用于创建
REST客户端的API凭据,可以执行您想要的操作。我假设您的类定义如下:

public class ActivateRedirects : IRule
{
    private readonly CoreSettings _coreSettings;

    public ActivateRedirects(CoreSettings coreSettings)
    {
        _coreSettings = coreSettings;
    }

    public void ApplyRule(RewriteContext context)
    {
        
    }
}
如前所述,读取配置文件:

services.Configure<CoreSettings>(root.GetSection("Website"));
如果在
ActivateRedirects
中放置断点并发送请求,您将看到
CoreSettings
字段已填充

更新 我认为这个场景正是
IOptionsMonitor
的设计目标。它已注册为单例,但会收到选项更改的通知。将
activateredirections
更改为:

public class ActivateRedirects : IRule
{
    private readonly IOptionsMonitor<CoreSettings> _coreSettings;

    public ActivateRedirects(IOptionsMonitor<CoreSettings> coreSettings)
    {
        _coreSettings = coreSettings;
    }

    public void ApplyRule(RewriteContext context)
    {
        
    }
}
public类ActivateRedirects:IRule
{
专用只读IOptionsMonitor\u coreSettings;
公共激活指示(IOptionsMonitor核心设置)
{
_coreSettings=coreSettings;
}
public void ApplyRule(重写上下文)
{
}
}
并将实例的构造方式更改为:

var coreSettings = app.ApplicationServices.GetRequiredService<IOptionsMonitor<CoreSettings>>();
var activateRedirects = new ActivateRedirects(coreSettings);
var coreSettings=app.ApplicationServices.GetRequiredService();
var activateRedirects=新的activateRedirects(核心设置);

对我来说,编辑配置现在会在
CoreSettings
中显示更新的值。一个警告是,我不知道通知过程是如何工作的。如果最终在每个请求上直接读取配置,那么它的扩展性将非常差,因此我建议先对其进行一次良好的测试。

谢谢。这似乎是可行的,我以前的错误是尝试使用
IOptionsSnapshot
而不是
IOptions
。然而,这其中有一个原因(我应该在我的问题中明确说明),那就是我希望它能够进行配置更改,但我从我所尝试的所有方法中猜测,您的方法是我仅有的工作代码方法,我真的不能这么做@JamieHartnoll问题是,
IOptions
的生命周期是单例的,这就是为什么它不接收对配置所做的更改。但是
IOptionsSnapshot
的作用域是限定的,这意味着它的持续时间是针对请求的,但这是由容器管理的。由于作为规则添加的
ActivateRedirects
实例将在整个应用程序中存在,它将在相同的时间内保持对
IOptionsSnapshot
的引用处于活动状态,因此永远不会获取配置更改。是的,这就是我现在开始理解它的方式!据我所知,这是因为
ActivateRedirects
实例在整个应用程序中都有生命周期,因此依赖某个具有请求生命周期的对象是没有意义的,它可能会造成这样一种情况:始终存在的
ActivateRedirects
没有
CoreSettings
对象来绘制其依赖数据?@JamieHartnoll几乎正确。对于作用域实例,它们是由容器根据请求创建的。但是使用
ActivateRedirects
,它的生存期不是由容器管理的,因此它会保留对传递给它的
IOptionsSnapshot
的初始实例的引用,因此永远不会提供更新的配置。@JamieHartnoll,但我刚刚发现
IOptionsMonitor
,这可能会解决您的问题。给我几分钟,我会更新我的答案。
public class ActivateRedirects : IRule
{
    private readonly IOptionsMonitor<CoreSettings> _coreSettings;

    public ActivateRedirects(IOptionsMonitor<CoreSettings> coreSettings)
    {
        _coreSettings = coreSettings;
    }

    public void ApplyRule(RewriteContext context)
    {
        
    }
}
var coreSettings = app.ApplicationServices.GetRequiredService<IOptionsMonitor<CoreSettings>>();
var activateRedirects = new ActivateRedirects(coreSettings);