Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用IConfigureOptions配置注入依赖项_C#_Asp.net_Asp.net Core_.net Core_Asp.net Core Mvc - Fatal编程技术网

C# 使用IConfigureOptions配置注入依赖项

C# 使用IConfigureOptions配置注入依赖项,c#,asp.net,asp.net-core,.net-core,asp.net-core-mvc,C#,Asp.net,Asp.net Core,.net Core,Asp.net Core Mvc,我已经创建了一个ASP.NET Core 1.0.1 WebApi项目,并试图在控制器中使用注入依赖项之前,使用一些自定义选项初始化它。在网上搜索之后,我找到了几篇文章(,并解释了如何使用IConfigureService来完成这项工作。看起来很简单!不幸的是,我无法让它工作,我也不知道为什么,我确信这一定是一个简单的疏忽 我创建了一个简单的项目,并添加了以下类来说明最基本的场景: public class Tester { public void Initialize(TestOpti

我已经创建了一个ASP.NET Core 1.0.1 WebApi项目,并试图在控制器中使用注入依赖项之前,使用一些自定义选项初始化它。在网上搜索之后,我找到了几篇文章(,并解释了如何使用IConfigureService来完成这项工作。看起来很简单!不幸的是,我无法让它工作,我也不知道为什么,我确信这一定是一个简单的疏忽

我创建了一个简单的项目,并添加了以下类来说明最基本的场景:

public class Tester
{
    public void Initialize(TestOptions options)
    {
        //do something with options.
    }
}

public class TestConfigurator : IConfigureOptions<TestOptions>
{
    private Tester _tester;

    public TestConfigurator(Tester tester)
    {
        _tester = tester;
    }

    public void Configure(TestOptions options)
    {
        _tester.Initialize(options);
    }
}

public class TestOptions
{
}
公共类测试器
{
公共void初始化(TestOptions)
{
//用选项做点什么。
}
}
公共类TestConfigurator:IConfigureOptions
{
私人测试员(u测试员),;
公共测试配置器(测试仪)
{
_测试员=测试员;
}
公共void配置(TestOptions选项)
{
_初始化(选项);
}
}
公共类测试选项
{
}
“Tester”类被注入控制器类的构造函数中:

[Route("api/[controller]")]
public class ValuesController : Controller
{
    public ValuesController(Tester tester)
    {
        //do something with tester..
    }
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }
}
[路由(“api/[控制器]”)]
公共类值控制器:控制器
{
公共价值控制人(测试人员)
{
//用测试仪做点什么。。
}
//获取api/值
[HttpGet]
公共IEnumerable Get()
{
返回新字符串[]{“value1”,“value2”};
}
}
最后,我在Startup类的ConfigureServices中添加了以下配置:

    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.AddOptions();
        services.AddMvc();
        services.AddSingleton<Tester, Tester>();
        services.AddSingleton<IConfigureOptions<TestOptions>, TestConfigurator>();
    }
public void配置服务(IServiceCollection服务)
{
//添加框架服务。
services.AddApplicationInsightsTelemetry(配置);
services.AddOptions();
services.AddMvc();
services.AddSingleton();
services.AddSingleton();
}
当我运行项目并调用“api/values”调用时,会创建Tester类并将其注入ValuesController,但TestConfigurator类从未构造,因此该类从未使用options类初始化。我缺少什么

更新
下面的答案当然对这个简化的例子都是有效的。我现在意识到我有点过于简化了,因为我使用的依赖关系(这里以Tester的形式演示)来自第三方库,因此我没有构造函数。将第三方类包装在扩展类中可以实现这一目的,但是如果有人对在不修改其构造函数的情况下操作它有其他建议,那么我仍然愿意接受建议,谢谢。

好的,现在我知道了,我觉得所有的编辑都很愚蠢

你把
IOptions
用错了,把我弄糊涂了

实现自定义
IConfigurationOptions
使您能够从数据库配置选项,或者只使用不同的类(而不是lambda)

您试图做的是基于这些选项实例化一个Tester类,这很好,但这不是
IConfigureOptions
工作

为了根据
TestOptions
初始化您的
Tester
类,您应该在
Tester
类上创建一个构造函数,该构造函数如下所示

public class Tester
{
    public Tester(IOptions<TestOptions> options)
    {
        //do something with options.
    }
}
公共类测试器
{
公共测试仪(IOPS选项)
{
//用选项做点什么。
}
}
你所做的一切都会奏效。

摘自并适应你的例子

假定

public class TestOptions {
    public string SomeOption { get; set; }
}
可以使用
IOptions
accessor服务

您可以尝试提取
Tester
并将其注册到服务集合中

public interface ITester {
    //tester contract    
}

public class Tester : ITester {
    public Tester(IOptions<TestOptions> options) {
        //do something with test options.
    }
}
最后,只需重构控制器,使其依赖于抽象而不是具体化

[Route("api/[controller]")]
public class ValuesController : Controller {
    public ValuesController(ITester tester) {
        //do something with tester..
    }
    // GET api/values
    [HttpGet]
    public IEnumerable<string> Get() {
        return new string[] { "value1", "value2" };
    }
}
[路由(“api/[控制器]”)]
公共类值控制器:控制器{
公共价值控制人(ITester测试仪){
//用测试仪做点什么。。
}
//获取api/值
[HttpGet]
公共IEnumerable Get(){
返回新字符串[]{“value1”,“value2”};
}
}

测试选项应该从哪里来?您是否试图从设置文件中自动神奇地映射它?我认为您在考虑这应该如何工作,除非出于某种原因,您必须使用
初始化
,而不是构造函数注入

您所要做的就是让测试人员可以使用一些选项,对吗

如果是这样,只需使用基本的
IOptions
功能-无需使用
IConfigureOptions

public class Tester
{
    private TestOptions _options;
    public Tester(IOptions<TestOptions> options)
    {
       _options = options.Value;
    }
}
// don't need this anymore
/* public class TestConfigurator : IConfigureOptions<TestOptions>
{
    private Tester _tester;

    public TestConfigurator(Tester tester)
    {
        _tester = tester;
    }

    public void Configure(TestOptions options)
    {
        _tester.Initialize(options);
    }
}
*/
public class TestOptions
{
}
公共类测试器
{
私有测试选项_选项;
公共测试仪(IOPS选项)
{
_选项=选项.值;
}
}
//我不再需要这个了
/*公共类TestConfigurator:IConfigureOptions
{
私人测试员(u测试员),;
公共测试配置器(测试仪)
{
_测试员=测试员;
}
公共void配置(TestOptions选项)
{
_初始化(选项);
}
}
*/
公共类测试选项
{
}
然后使用以下两种方法之一配置选项(取决于它是来自配置还是必须手动构造)

public void配置服务(IServiceCollection服务)
{
//添加框架服务。
services.AddApplicationInsightsTelemetry(配置);
services.AddOptions();
services.AddMvc();
services.AddSingleton();
//使用config配置TestOptions
服务。配置(配置);
//使用代码配置MyOptions
services.Configure(testOptions=>
{
//在此处初始化它们,例如testOptions.Foo=“Bar”
});
}

我是否遗漏了一些内容,或者您需要将
服务添加到
ConfigureServices();
方法中以注册
TestConfigurator
类型?您是否收到异常,或者它是否仅等于null?没有异常,并且对象不为null,例如
public class Tester
{
    private TestOptions _options;
    public Tester(IOptions<TestOptions> options)
    {
       _options = options.Value;
    }
}
// don't need this anymore
/* public class TestConfigurator : IConfigureOptions<TestOptions>
{
    private Tester _tester;

    public TestConfigurator(Tester tester)
    {
        _tester = tester;
    }

    public void Configure(TestOptions options)
    {
        _tester.Initialize(options);
    }
}
*/
public class TestOptions
{
}
public void ConfigureServices(IServiceCollection services)
{
        // Add framework services.
        services.AddApplicationInsightsTelemetry(Configuration);
        services.AddOptions();
        services.AddMvc();
        services.AddSingleton<Tester, Tester>();
        // Configure TestOptions using config 
        services.Configure<TestOptions>(Configuration);

        // Configure MyOptions using code
        services.Configure<TestOptions>(testOptions =>
        {
           // initialize them here, e.g. testOptions.Foo = "Bar"
        });
}