【问题标题】:.Net Core How to Access Configuration Anywhere in application.Net Core 如何在应用程序中的任何位置访问配置
【发布时间】:2019-02-20 17:04:58
【问题描述】:

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

我做了以下事情:

应用设置:

{
  "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"
  }
}

我的配置:

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 之间有什么区别?我将两者都视为注册服务的一种方式。

【问题讨论】:

  • 使用services.Configure&lt;MyConfig&gt;(configuration.GetSection("ConnectionStrings")) 而不是services.AddXXX&lt;...&gt;()。并在服务中,在构造函数参数中添加IOptions&lt;MyConfig&gt; options

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


【解决方案1】:

我会说,在 .Net Core 应用程序中,您不应该将 IConfiguration 的实例传递给您的控制器或其他类。您应该改用通过IOtions&lt;T&gt; 注入的强类型设置。将其应用于您的案例,修改 MyConfig 类(属性名称也应与配置中的名称匹配,因此您必须重命名配置(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?我将两者都视为注册服务的一种方式。

瞬态生命周期服务在每次被请求时创建。

Scoped 生命周期服务为每个请求创建一次。

【讨论】:

  • 这似乎奏效了,但我的挑战/问题仍然相同。如何调用 MyService?实例化时是否必须在 MyConfig 对象中传递它?我基本上是在尝试从我的启动类中调用 MyService 中的方法:
  • 我已经编辑了我的初始帖子以在我的启动类中添加代码,该类试图调用依赖于依赖注入的 Something 类。我已经进行了您向@Alex Riabov 建议的更改并且它们有效,但我需要帮助弄清楚如何从我的启动课程中调用Something,如我帖子中的编辑中所述。
  • @mo_maat 想要实现什么?我不确定我是否从您的编辑中理解了这一点
  • 在您的 HandleGetData 方法中,您需要从 DI 系统中检索类。将Something something = new Something(); 行替换为var something = app.ApplicationServices.GetService&lt;Something&gt;();。 DI 系统将创建Something 类并为您注入IOptions&lt;&gt; 服务。
  • @AlexRiabov @SimplyGed 我已经对帖子进行了更改,以显示我的代码现在看起来像所有建议的编辑。总结一下我的问题,我希望能够从我的 Startup 类中的 HandleData 函数调用 DataHelper。然后 DataHelper 将返回一个字符串(最终的想法是根据 appsettings 中的连接字符串从数据库中返回数据)。就目前而言,我收到以下错误:`NullReferenceException: Object reference not set to an instance of an object.
【解决方案2】:

您必须为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"];
    }
}

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

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 之间有什么区别?我将两者都视为注册服务的一种方式。

这是来自微软的详细信息:

Service Lifetime details in ASP.NET Core

【讨论】:

    猜你喜欢
    • 2019-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-21
    • 2021-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多