我想知道是否有办法在不使用依赖注入的情况下访问Configuration(Microsoft.Extensions.Configuration)。我看到的只有一些例子是通过构造函数注入(使用IOptions或直接注入Configuration)。
我的困境是我有一个实用工具类 - 而不是服务 - 它有静态方法来动态地做事。在一些静态方法中,我想动态地从appsettings.json中检索几个属性。由于这是一个严格的实用程序类,我不希望必须将此类注入需要使用该实用程序中的一个或两个方法的其他每个类。
关于如何在没有某种依赖注入的情况下访问appsettings.json的属性的任何想法。
仅供参考:使用c#和.net核心1.1
答案 0 :(得分:20)
如果您使用带有单个公共构造函数的标准AppSettings类,该构造函数采用可用于填充所有AppSettings属性的IConfiguration,这将保留依赖注入的能力。
如果在构造函数的末尾我们设置了一个指向当前AppSettings实例的静态属性“Current”,这将允许我们通过静态属性从该点开始访问设置,而无需进一步注入。 / p>
如果我们现在创建一个静态的默认'GetCurrentSettings'方法来从json文件中获取设置,这可以用作默认实例化,这样如果调用'Current'并将其设置为null,我们就会离开并填充文件中的设置。这是我的意思的一个例子......
public class AppSettings
{
private static AppSettings _appSettings;
public string AppConnection { get; set; }
public AppSettings(IConfiguration config)
{
this.AppConnection = config.GetValue<string>("AppConnection");
// Now set Current
_appSettings = this;
}
public static AppSettings Current
{
get
{
if(_appSettings == null)
{
_appSettings = GetCurrentSettings();
}
return _appSettings;
}
}
public static AppSettings GetCurrentSettings()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
IConfigurationRoot configuration = builder.Build();
var settings = new AppSettings(configuration.GetSection("AppSettings"));
return settings;
}
}
因此,您可以在代码AppSettings.Current.AppConnection
中调用任何地方如果已使用DI实例化,则将检索注入的版本,否则将从appsettings.json文件中获取默认版本。我怀疑它是否满足每个人,我不确定我是否已经解释得很好,但希望它有意义。
答案 1 :(得分:4)
我刚刚在Startup
static:
public static IConfiguration Configuration { get; set; }
现在,我只需Startup.Configuration
即可在应用程序的任何位置访问它。
答案 2 :(得分:3)
我有一个实用类 - 不是服务 - 有静态方法
这真的是你问题的核心。你有静态的方法与依赖,这不是DI友好。
我认为你有一个很好的候选人,你已经成为一个实用工具类。这样做会导致您无法正确使用DI。要么将类设为实例类,要么将适用的功能提取到服务中,您将有一个注入IOptions
依赖关系的途径。
对于任何具有(或可能具有)依赖关系的东西,你应该避免使用静态类/方法。
答案 3 :(得分:0)
我完全同意@Hoot建议的解决方案,但我修改了类很少。我修改了类,因为我需要传递动态Key来获取相同的值..
配置类:
public class ConfigHelper
{
private static ConfigHelper _appSettings;
public string appSettingValue { get; set; }
public static string AppSetting(string Key)
{
_appSettings = GetCurrentSettings(Key);
return _appSettings.appSettingValue;
}
public ConfigHelper(IConfiguration config, string Key)
{
this.appSettingValue = config.GetValue<string>(Key);
}
public static ConfigHelper GetCurrentSettings(string Key)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
IConfigurationRoot configuration = builder.Build();
var settings = new ConfigHelper(configuration.GetSection("AppSettings"), Key);
return settings;
}
}
Appsettings.Json配置:
"AppSettings": {
"WebApplicationUrl": "http://localhost:0000/",
"ServiceUrl": "http://localhost:0000/",
"CommonServiceUrl": "http://localhost:0000/"
}
致电示例:
string ServiceUrl = ConfigHelper.AppSetting("ServiceUrl");
所以从现在起我们就可以传递动态密钥了。
答案 4 :(得分:0)
我已将@Ankit Mori 的答案修改为更好的动态解决方案,并且还具有强类型属性。
using System.IO;
using Microsoft.Extensions.Configuration;
public class AppSettings
{
#region Methods
public static string GetSettingValue(string MainKey, string SubKey)
{
return Configuration.GetSection(MainKey).GetValue<string>(SubKey);
}
#endregion
#region Properties
public static IConfigurationRoot _configuration;
public static IConfigurationRoot Configuration
{
get
{
if (_configuration == null)
{
IConfigurationBuilder builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddEnvironmentVariables();
_configuration = builder.Build();
}
return _configuration;
}
}
public static string MainAPI
{
get
{
return Configuration.GetSection("AppSettings").GetValue<string>("AppConnection");
}
}
#endregion
}