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