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

时间:2015-05-25 17:17:29

标签: 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; 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();
  }

AppSettings.cs

public class AppSettings
{
 public string ContactEmailAddress { get; set; }
}

config.json

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

OrderController.cs

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

Order.cs

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

如上例所示,我将AppSettings传递给整个堆栈。这感觉不正确。为了进一步担心,如果我尝试使用需要访问配置设置的第三方库,这种方法将无效。第三方库如何访问配置设置?我误会了什么吗?有更好的方法吗?

1 个答案:

答案 0 :(得分:11)

您正在纠缠2个不同的运行时资源提供程序, 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>();
   }

然后,如果我们的家庭控制器需要访问您的EmailService,我们通过将其作为参数添加到Controller构造函数来添加对它的接口的依赖

public class HomeController : Controller
{
   private readonly IEmailService _emailService;
   private readonly string _emailContact;

  /// The framework will inject an instance of an IEmailService implementation.
   public HomeController(IEmailService emailService)
   {
      _emailService = emailService;
      _emailContact = System.Configuration.ConfigurationManager.
                   AppSettings.Get("ContactEmail");
   }

   [HttpPost]
   public void EmailSupport([FromBody] string message)
   {
      if (!ModelState.IsValid)
      {
         Context.Response.StatusCode = 400;
      }
      else
      {
         _emailService.Send(_emailContact, message);

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

在上一个示例中,在我们的应用程序Startup中,我们将DI工厂配置为将IEmailService的应用程序请求与EmailService相关联。因此,当我们的控制器由 MVC框架实例化时,框架会注意到我们的Home Controller期望IEmailService,框架会检查我们的应用程序服务集合。它找到映射指令并将Singleton EmailService(占用接口的后代)注入我们的Home Controller。

Super Polymorphic Factorific - alodocious!

为什么这很重要?

如果您的联系电子邮件发生更改,则更改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>();
   }