.Net Core如何在应用程序中的任何地方访问配置

时间:2018-09-16 17:02:52

标签: asp.net-core dependency-injection .net-core

我已通读了有关.Net Core 2.1中不同的设置和访问配置方式的文档,以及似乎推荐使用的选项模式(https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1)。但是,我似乎无法获得想要的工作:

我已经执行以下操作:

AppSettings:

{
  "ConnectionStrings": {
    "DefaultConnStr": "Server=(localdb)\\MSSQLLocalDB;Database=_CHANGE_ME;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=true",
    "AW2012ConnStr": "Server=localhost;Database=AW2012;Trusted_Connection=True;MultipleActiveResultSets=true;Integrated Security=true"
  }
}

MyConfig:

public class MyConfig
{
    public string AWConnStr { get; }
    public string DefaultConnStr { get; }
}

启动:

public class Startup
{

public IConfiguration _config { get; set; }

public Startup(IHostingEnvironment env)
{
     var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
     _config = builder.Build();

}

public void ConfigureServices(IServiceCollection services)
{
      services.AddOptions();

      //add config to services for dependency injection
      //services.AddTransient<IMyConfig, MyConfig>();
     //services.AddScoped<IMyConfig, MyConfig>();
     var section = _config.GetSection("ConnectionStrings");
     services.Configure<MyConfig>(section);
}

    private static void HandleGetData(IApplicationBuilder app)
    {
        //DataHelper dataHelper = new DataHelper(_dataHelper);
        var _dataHelper = app.ApplicationServices.GetService<DataHelper>();

        app.Run(async context =>
        {
            //await context.Response.WriteAsync("<b>Get Data</b>");
            //await context.Response.WriteAsync(dataHelper.GetCompetitions(context.Request.QueryString.ToString()));
            await context.Response.WriteAsync(_dataHelper.GetCompetitions(context.Request.QueryString.ToString()));
        });
    }


  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            app.Map("/Route1", HandleRoute1);

            app.Map("/Route2", HandleRoute2);

            app.Map("/GetData", HandleGetData);

            app.Run(async (context) =>
            {
                await context.Response.WriteAsync("Non Mapped Default");
            });
        }
 }

然后我想在代码中任何位置的任何类中访问配置。因此,例如,我有以下课程仅想读取配置信息:

public interface IDataHelper
{
    string GetCompetitions(string val);
}

public class DataHelper : IDataHelper
{
    private readonly MyConfig _settings;

    public DataHelper(IOptions<MyConfig> options)
    {
        _settings = options.Value;
    }

    public string GetCompetitions( string queryStringVals)
    {

        return _settings.AWConnStr;

    } 
}

如上面在Startup类中所示,然后我想在启动时访问/调用HandleGetData函数,以便在浏览以下路径时:http://localhost:xxxxx/getdata从Something中获取响应。 GetData函数。

这是正确的吗?我遇到的问题是,当我创建Something类的实例时,它要求我传入配置对象,但这并没有违反注入它的目的。我应该如何设置它以使其类似于DBContext如何使用配置选项注入上下文。并且services.AddTransient和services.AddScoped之间有什么区别?我把这两种方法都注册为服务。

2 个答案:

答案 0 :(得分:3)

我想说的是,在.Net Core应用程序中,您不应将IConfiguration的实例传递给控制器​​或其他类。您应该使用通过IOtions<T>注入的强类型设置。将其应用于您的案例,修改MyConfig类(属性名称也应与config中的名称匹配,因此您必须重命名config(DefaultConnection-> DefaultConnStr,AW2012ConnStr-> AWConnStr或属性反之亦然):

public class MyConfig
{    
    public string AWConnStr { get; set; }
    public string DefaultConnStr { get; set; }
}

注册:

public void ConfigureServices(IServiceCollection services)
{
    // in case config properties specified at root level of config file
    // services.Configure<MyConfig>(Configuration);

    // in case there are in some section (seems to be your case)
    var section = Configuration.GetSection("ConnectionStrings");
    services.Configure<MyConfig>(section);
}

将其注入所需的服务:

public class MyService
{
    private readonly MyConfig _settings;

    public MyService(IOptions<MyConfig> options)
    {
        _settings = options.Value;
    }
}
  

services.AddTransient和   services.AddScoped?我把这两种方法都注册为服务。

每次请求时都会创建

临时终生服务。

每个请求一次创建

作用域终生服务。

答案 1 :(得分:0)

对于Something,您必须对MyConfig做相同的事情,例如:

public interface ISomething
{
    string GetSomeData();
}

然后:

public class Something : ISomething
{
    public IConfiguration _config { get; set; }

    public Something(IConfiguration configuration)
    {
        _config = configuration;
    }

    public string GetSomeData()
    {
        return _config["DefaultConnStr"];
    }
}

然后在ConfigureService类的Startup方法中,如下所示:

services.AddScoped<ISomething,Something>();

然后按如下所示调用GetSomeData()

public class CallerClass
{
     public ISomething _something { get; set; }

     public CallerClass(ISomething something)
     {
            _something = something;
     }

     public string CallerMethod()
     {
         return _something.GetSomeData();
     }
}

然后:

  

services.AddTransient和services.AddScoped有什么区别?我把这两种方法都注册为服务。

这是来自Microsoft的详细信息:

Service Lifetime details in ASP.NET Core