开发自己的配置提供者
在项目实际的开发过程中,我们往往需要使用自己自定义的配置信息,同时也包括从不同的源头获取配置信息,以便灵活的修改项目配置
-
利用IConfigurationProvider接口,来实现自定义的配置提供者,这里是从项目目录下的文件读取的,所以我们用继承了该接口下面的FIleConfigurationProvider抽象方法来实现
1.第一步:我们在目录下新建一个web.config文件,定义一些配置:
2.第二步,新建一个FxConfigurationProvider类继承自FIleConfigurationProvider,然后重写Load方法,定义一个Dictionary用来获取文件中的配置信息,转化为键值对的形式存储,利用XmlDocument类来读取web.config中的内容。并且把数据传到父类的Data数据中;
public class FxConfigurationProvider : FileConfigurationProvider
{
private FxConfigurationSource _fxConfigurationSource;
public FxConfigurationProvider(FxConfigurationSource source):base(source)
{
_fxConfigurationSource = source;
}
public override void Load(Stream stream)
{
//建立一个键不分大小写的字典
var data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
//Xml读取
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(stream);
//读取连接串
var connNodes = xmlDoc.SelectNodes("/configuration/connectionStrings/add");
foreach (XmlNode node in connNodes)
{
string name = node.Attributes["name"].Value;
string connectionString = node.Attributes["connectionString"].Value;
var attrProviderName = node.Attributes["providerName"];
//
data[$"{name}:connectionString"] = connectionString;
if (attrProviderName is object)
{
data[$"{name}:providerName"] = attrProviderName.Value ;
}
}
//读取Appsettings
var settingNodes = xmlDoc.SelectNodes("/configuration/appSettings/add");
foreach (XmlNode node in settingNodes)
{
string key = node.Attributes["key"].Value;
string value = node.Attributes["value"].Value;
data[$"{key}"] = value;
}
this.Data = data;
}
}
3.新增一个FxConfigurationSource继承抽象方法ConfigurationSource,在重载方法Build中返回一个新的FxConfigurationProvider对象实例;(注意,这里要写 EnsureDefaults(builder);保证能从配置文件中读取所有配置 )
public class FxConfigurationSource : FileConfigurationSource
{
public override IConfigurationProvider Build(IConfigurationBuilder builder)
{
EnsureDefaults(builder);
return new FxConfigurationProvider(this);
}
}
4.新建一个WebConfig类,用来接收从文件中获取的配置参数的值,包扩连接串和一些其他的配置
public class WebConfig
{
public ConnectStr Conn1 { get; set; }
public ConnectStr ConnTest { get; set; }
public AppSettings AppSettings { get; set; }
}
public class ConnectStr
{
public string ConnectionString { get; set; }
public string ProviderName { get; set; }
}
5.新建一个TestWebConfig类型,使用IOptionsSnapshot接口来动态获取配置信息;
public class TestWebConfig
{
private IOptionsSnapshot<WebConfig> _optWc;
public TestWebConfig(IOptionsSnapshot<WebConfig> options)
{
_optWc = options;
}
public void Test()
{
var wc = _optWc.Value;
Console.WriteLine(wc.Conn1.ConnectionString);
Console.WriteLine(wc.AppSettings.age);
Console.WriteLine(wc.AppSettings.proxy.address);
}
}
6.在main方法中注入相关的类,以及定义相关的配置方法,
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestWebConfig>();
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.Add(new FxConfigurationSource() { Path="web.config"});
IConfigurationRoot configurationRoot = configurationBuilder.Build();
//Config配置注入
services.AddOptions().Configure<WebConfig>(e => configurationRoot.Bind(e));
using (ServiceProvider sp = services.BuildServiceProvider())
{
var test = sp.GetRequiredService<TestWebConfig>();
test.Test();
}
}
7.运行结果如下
开发数据库配置提供者:
- 某些网站用集群部署,如果用本地配置文件,每次修改都要挨个修改。有Apolo、Nacos等开源的配置中心以及云服务平台的配置服务,但是项目对于配置的要求没有非常复杂,因此决定在关系数据库中保存配置
1.我们首先在Mysql数据库中创建配置表T_configs,并新增三个字段,id,name ,value,给表维护一条记录
2.定义数据库连接串,并通过configurationBuilder.AddDbConfiguration方法,添加一个数据库配置,并安装MySql.Data.MySqlClient包,在AddDbConfiguration方法中传递一个MySqlConnection对象的实例,此实例中用前面定义的连接串作为参数;
3.运行结果如下:
配置文件的安全性:
- 注意,我们在项目开发的过程中,如果版本控制工具的服务器不是在内网而是直接在外网比如GitHub中时,此时最好不要把配置文件上传到服务器上,因为这样会造成一些机密信息的泄露,比如数据库用户和密码等;
- 我们可以用user-secrets功能,将机密配置信息存储到本地特定的文件夹,版本控制工具不会识别到该文件,也不会上传到服务器;
1.项目右键->管理用户机密,这时VS会提示我们需要安装一nuGet包,点击安装即可,
2.这时候程序会自动生成一个secrets.json文件,我们把需要配置的信息放到其中:
3.然后在注册配置信息的时候使用进行注册,传递参数为当前的类,然后再其他类型的配置文件中,将这两个加密的配置删除掉即可
static void Main(string[] args)
{
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.AddUserSecrets<Program>();
}
4.然后在项目打包部署到生产环境时,在配置文件中手动添加这些加密的配置即可;