C# 在ASP.NET 5(vNext)中获取配置值

C# 在ASP.NET 5(vNext)中获取配置值,c#,asp.net,asp.net-mvc,asp.net-core,asp.net-core-mvc,C#,Asp.net,Asp.net Mvc,Asp.net Core,Asp.net Core Mvc,我正在ASP.NET 5(vNext)中努力学习一些概念 其中之一是用于配置的依赖项注入方法。似乎我必须在堆栈中传递一个参数。我可能误解了什么或做错了什么 假设我有一个名为“contactEmailAddress”的配置属性。我将使用该配置属性在下新订单时发送电子邮件。考虑到这种情况,我的ASP.NET 5堆栈将如下所示: Startup.cs public class Startup { public IConfiguration Configuration { get;

我正在ASP.NET 5(vNext)中努力学习一些概念

其中之一是用于配置的依赖项注入方法。似乎我必须在堆栈中传递一个参数。我可能误解了什么或做错了什么

假设我有一个名为“contactEmailAddress”的配置属性。我将使用该配置属性在下新订单时发送电子邮件。考虑到这种情况,我的ASP.NET 5堆栈将如下所示:

Startup.cs

public class Startup
{        
  public IConfiguration Configuration { get; set; }
  public Startup(IHostingEnvironment environment)
  {
    var configuration = new Configuration().AddJsonFile("config.json");
    Configuration = configuration;
  }

  public void ConfigureServices(IServiceCollection services)
  {
    services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
    services.AddMvc();
  }

  public void Configure(IApplicationBuilder app)
  {
    app.UseErrorPage();
    app.UseMvc(routes =>
      {
        routes.MapRoute("default",
          "{controller}/{action}/{id}",
          defaults: new { controller = "Home", action = "Index" });
      }
    );
    app.UseWelcomePage();
  }
public class AppSettings
{
 public string ContactEmailAddress { get; set; }
}
[Route("orders")]
public class OrdersController : Controller
{    
  private IOptions<AppSettings> AppSettings { get; set; }

  public OrdersController(IOptions<AppSettings> appSettings)
  {
    AppSettings = appSettings;
  }

  [HttpGet("new-order")]
  public IActionResult OrderCreate()
  {
    var viewModel = new OrderViewModel();
    return View(viewModel);
  }

  [HttpPost("new-order")]
  public IActionResult OrderCreate(OrderViewModel viewModel)
  {

    return new HttpStatusCodeResult(200);
  } 
}
public class Order()
{
  public void Save(IOptions<AppSettings> appSettings)
  {
    // Send email to address in appSettings
  }

  public static List<Order> FindAll(IOptions<AppSettings> appSettings)
  {
    // Send report email to address in appSettings
    return new List<Order>();
  }
}
config.json

{
  "AppSettings": {
    "ContactEmailAddress":"support@mycompany.com"  
  }
}
OrderController.cs

public class Startup
{        
  public IConfiguration Configuration { get; set; }
  public Startup(IHostingEnvironment environment)
  {
    var configuration = new Configuration().AddJsonFile("config.json");
    Configuration = configuration;
  }

  public void ConfigureServices(IServiceCollection services)
  {
    services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
    services.AddMvc();
  }

  public void Configure(IApplicationBuilder app)
  {
    app.UseErrorPage();
    app.UseMvc(routes =>
      {
        routes.MapRoute("default",
          "{controller}/{action}/{id}",
          defaults: new { controller = "Home", action = "Index" });
      }
    );
    app.UseWelcomePage();
  }
public class AppSettings
{
 public string ContactEmailAddress { get; set; }
}
[Route("orders")]
public class OrdersController : Controller
{    
  private IOptions<AppSettings> AppSettings { get; set; }

  public OrdersController(IOptions<AppSettings> appSettings)
  {
    AppSettings = appSettings;
  }

  [HttpGet("new-order")]
  public IActionResult OrderCreate()
  {
    var viewModel = new OrderViewModel();
    return View(viewModel);
  }

  [HttpPost("new-order")]
  public IActionResult OrderCreate(OrderViewModel viewModel)
  {

    return new HttpStatusCodeResult(200);
  } 
}
public class Order()
{
  public void Save(IOptions<AppSettings> appSettings)
  {
    // Send email to address in appSettings
  }

  public static List<Order> FindAll(IOptions<AppSettings> appSettings)
  {
    // Send report email to address in appSettings
    return new List<Order>();
  }
}
[路线(“订单”)]
公共类OrdersController:控制器
{    
私有IOptions应用设置{get;set;}
公共医嘱控制器(IOptions appSettings)
{
AppSettings=AppSettings;
}
[HttpGet(“新订单”)]
public IActionResult OrderCreate()
{
var viewModel=new OrderViewModel();
返回视图(viewModel);
}
[HttpPost(“新订单”)]
公共IActionResult OrderCreate(OrderViewModel viewModel)
{
返回新的HttpStatusCodeResult(200);
} 
}
订单.cs

public class Startup
{        
  public IConfiguration Configuration { get; set; }
  public Startup(IHostingEnvironment environment)
  {
    var configuration = new Configuration().AddJsonFile("config.json");
    Configuration = configuration;
  }

  public void ConfigureServices(IServiceCollection services)
  {
    services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
    services.AddMvc();
  }

  public void Configure(IApplicationBuilder app)
  {
    app.UseErrorPage();
    app.UseMvc(routes =>
      {
        routes.MapRoute("default",
          "{controller}/{action}/{id}",
          defaults: new { controller = "Home", action = "Index" });
      }
    );
    app.UseWelcomePage();
  }
public class AppSettings
{
 public string ContactEmailAddress { get; set; }
}
[Route("orders")]
public class OrdersController : Controller
{    
  private IOptions<AppSettings> AppSettings { get; set; }

  public OrdersController(IOptions<AppSettings> appSettings)
  {
    AppSettings = appSettings;
  }

  [HttpGet("new-order")]
  public IActionResult OrderCreate()
  {
    var viewModel = new OrderViewModel();
    return View(viewModel);
  }

  [HttpPost("new-order")]
  public IActionResult OrderCreate(OrderViewModel viewModel)
  {

    return new HttpStatusCodeResult(200);
  } 
}
public class Order()
{
  public void Save(IOptions<AppSettings> appSettings)
  {
    // Send email to address in appSettings
  }

  public static List<Order> FindAll(IOptions<AppSettings> appSettings)
  {
    // Send report email to address in appSettings
    return new List<Order>();
  }
}
公共类顺序()
{
公共作废保存(IOptions应用设置)
{
//向appSettings中的地址发送电子邮件
}
公共静态列表FindAll(IOptions appSettings)
{
//将报告电子邮件发送到appSettings中的地址
返回新列表();
}
}

如上面的示例所示,我正在通过整个堆栈传递
AppSettings
。这感觉不正确。为了加深我的担忧,如果我试图使用需要访问配置设置的第三方库,这种方法将不起作用。第三方库如何访问配置设置?我是不是误解了什么?有更好的方法吗?

您正在纠缠两个不同的运行时资源提供程序,AppSettings依赖项注入

AppSettings,提供对特定于应用程序的值(如UICulture字符串、联系人电子邮件等)的运行时访问

DI容器是管理服务访问及其生命周期范围的工厂。例如,如果MVC控制器需要访问您的EmailService,您可以配置

   public void ConfigureServices(IServiceCollection services)
   {
      // Add all dependencies needed by Mvc.
      services.AddMvc();

      // Add EmailService to the collection. When an instance is needed,
      // the framework injects this instance to the objects that needs it
      services.AddSingleton<IEmailService, EmailService>();
   }

依赖注入的目的是管理服务的访问和生命周期

在上一个示例中,在我们的应用程序
启动
中,我们将DI工厂配置为将
IEmailService
的应用程序请求与
EmailService
相关联。因此,当我们的控制器被MVC框架实例化时,框架会注意到我们的
主控制器需要
IEmailService
,框架会检查我们的应用程序服务集合。它找到映射指令,并将一个
单例
电子邮件服务
(占用接口的后代)注入我们的家庭控制器

超级多态因子-孤独症

为什么这很重要?

如果您的联系人电子邮件发生更改,则更改
AppSetting
值并完成。来自
ConfigurationManager
的所有“ContactEmail”请求都会全局更改。弦很容易。当我们可以散列时,就不需要注射了

如果您的存储库、电子邮件服务、日志服务等发生更改,您需要一种全局方式来更改对此服务的所有引用。服务引用不像不可变的字符串文本那样容易传输。服务实例化应由工厂处理,以配置服务的设置和依赖项

因此,在一年内,您开发了一个
RobustMailService

Class RobustMailService : IEmailService
{

....

}
只要新的
RobustMailService
继承并实现
IEmailService
接口,您就可以通过更改以下内容来全局替换对邮件服务的所有引用:

   public void ConfigureServices(IServiceCollection services)
   {
      // Add all dependencies needed by Mvc.
      services.AddMvc();

      // Add RobustMailService to the collection. When an instance is needed,
      // the framework injects this instance to the objects that needs it 
      services.AddSingleton<IEmailService, RobustMailService>();
   }
public void配置服务(IServiceCollection服务)
{
//添加Mvc所需的所有依赖项。
services.AddMvc();
//将RobustMailService添加到集合。当需要实例时,
//框架将该实例注入到需要它的对象中
services.AddSingleton();
}

这可以通过使用IOptions评估服务来实现,就像您尝试的那样

我们可以从创建一个类开始,该类包含控制器从配置中需要的所有变量

public class VariablesNeeded
{
    public string Foo1{ get; set; }        
    public int Foo2{ get; set; }
}

public class OtherVariablesNeeded
{
    public string Foo1{ get; set; }        
    public int Foo2{ get; set; }
}
我们现在需要告诉中间件,控制器需要使用依赖项注入在控制器的构造函数中使用这个类,我们使用IOptions访问器服务来实现这一点

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;

public class MyController: Controller{    
    private readonly VariablesNeeded _variablesNeeded;

    public MyController(IOptions<VariablesNeeded> variablesNeeded) {
        _variablesNeeded= variablesNeeded.Value;
    }

    public ActionResult TestVariables() {
        return Content(_variablesNeeded.Foo1 + _variablesNeeded.Foo2);
    }
}
现在,我们需要确保管道实际为控制器提供此服务

在Startup类中的ConfigureServices方法中,您希望使用Options中间件,并将VariablesNeed类型的对象注入到管道中

public void ConfigureServices(IServiceCollection services)
{
   // Tells the pipeline we want to use IOption Assessor Services
   services.AddOptions();

   // Injects the object VariablesNeeded in to the pipeline with our desired variables
   services.Configure<VariablesNeeded>(x =>
   {
       x.Foo1 = Configuration["KeyInAppSettings"]
       x.Foo2 = Convert.ToInt32(Configuration["KeyParentName:KeyInAppSettings"])
   });

   //You may want another set of options for another controller, or perhaps to pass both to our "MyController" if so, you just add it to the pipeline    
   services.Configure<OtherVariablesNeeded>(x =>
   {
       x.Foo1 = "Other Test String",
       x.Foo2 = 2
   });

   //The rest of your configure services...
}
public void配置服务(IServiceCollection服务)
{
//告诉管道我们要使用IOption评估器服务
services.AddOptions();
//将插入到管道中的对象变量注入所需的变量
services.Configure(x=>
{
x、 Foo1=配置[“KeyInAppSettings”]
x、 Foo2=Convert.ToInt32(配置[“KeyParentName:KeyInAppSettings”])
});
//您可能需要另一个控制器的另一组选项,或者可能需要将这两个选项都传递给我们的“MyController”,如果需要,您只需将其添加到管道中即可
services.Configure(x=>
{
x、 Foo1=“其他测试字符串”,
x、 Foo2=2
});
//其余的配置服务。。。
}

有关更多信息,请参阅中有关使用选项和配置对象的章节。这是一个电子邮件地址还是多个地址?尽管您的答案非常详细,但@DavidMoores的答案实际上是正确的,因为他指定了如何通过confi