using EasyDevCore.Common;
using EasyDevCore.Configuration.Configuration;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace EasyDevCore.Configuration
{
///
///
///
public static class ConfigurationHelper
{
///
/// Gets the configuation root.
///
/// The section.
///
public static IConfigurationRoot GetConfiguationRoot(this IConfiguration section)
{
if (section is IConfigurationRoot)
{
return (IConfigurationRoot)section;
}
else
{
var fieldInfo = section.GetType().GetField("_root", BindingFlags.NonPublic | BindingFlags.Instance);
var root = fieldInfo.GetValue(section);
return (IConfigurationRoot)root;
}
}
///
/// Gets the application setting constants.
///
/// The configuration root.
///
public static Dictionary GetAppSettingConstants(this IConfigurationRoot configurationRoot)
{
var appContantsSection = configurationRoot.GetSection("AppSetting:Constants");
var envContantsSection = appContantsSection.GetSection("HOST-ENVIROMENT-VARIABLE");
Dictionary result = new();
foreach (var kp in appContantsSection.GetChildren().Where(kp => !kp.Key.Equals("HOST-ENVIROMENT-VARIABLE", StringComparison.InvariantCultureIgnoreCase)))
{
result[kp.Key] = kp.Value;
}
foreach (var kp in envContantsSection.GetChildren())
{
bool isPrefer = kp.Key.StartsWith("!");
string key = isPrefer ? kp.Key.Substring(1) : kp.Key;
string envValue = null;
if (!result.ContainsKey(key) || isPrefer)
{
envValue = Environment.GetEnvironmentVariable(kp.Value);
}
if (envValue != null)
{
result[key] = envValue;
}
}
return result;
}
///
/// Maps the application setting contants.
///
/// The builder.
///
public static IConfigurationBuilder MapAppSettingContants(this IConfigurationBuilder builder)
{
var root = (builder as IConfigurationRoot);
var appContantsSection = root.GetSection("AppSettings:Constants");
Dictionary constValues = new();
foreach (var kp in appContantsSection.GetChildren().Where(x => !string.IsNullOrWhiteSpace(x.Value)))
{
constValues[kp.Key] = kp.Value;
}
List placeHolders = new();
foreach (var kp in root.GetAllChildren().Where(x => !string.IsNullOrWhiteSpace(x.Value) && x.Value.Contains("{{") && x.Value.Contains("}}")))
{
placeHolders.Clear();
kp.Value.RegexGroupMatch(@"\{\{(?[^{}].*?)\}\}", (g) =>
{
if(constValues.ContainsKey(g.Value))
{
placeHolders.Add(g.Value);
}
});
foreach(var p in placeHolders)
{
kp.Value = kp.Value.Replace("{{" + p + "}}", constValues[p]);
}
}
return builder;
}
///
/// Gets the application setting constants.
///
/// The configuration root.
///
public static Dictionary GetAppSettingEnvConstants(this IConfigurationRoot configurationRoot)
{
Dictionary result = new Dictionary();
foreach (var kp in configurationRoot.GetSection("AppSetting:Constants:HOST-ENVIROMENT-VARIABLE").GetChildren())
{
result.Add(kp.Key, kp.Value);
}
return result;
}
///
/// Gets the configuration section.
///
/// The configuration.
/// Name of the section.
///
public static IConfigurationSection GetConfigMapEnvVariableSection(this IConfiguration configuration, string sectionName) => new EasyConfigurationSection(configuration.GetSection(sectionName));
///
/// Binds the configuration value.
///
/// The type of the model.
/// The section.
/// Name of the section.
///
public static TModel BindConfigEnvVariable(this IConfiguration section, string sectionName) where TModel : class
{
return section.GetConfigMapEnvVariableSection(sectionName).Bind();
}
private static string GetEnvironmentVariable(string key)
{
return Environment.GetEnvironmentVariable(key, EnvironmentVariableTarget.Process)
?? Environment.GetEnvironmentVariable(key, EnvironmentVariableTarget.User)
?? Environment.GetEnvironmentVariable(key, EnvironmentVariableTarget.Machine);
}
///
/// Translates the configuration value with enviroment macro.
///
/// The section.
/// The value.
/// The default value.
///
public static T ResolveConfigVariable(this IConfiguration section, string value, T defaultValue = default(T))
{
var root = section.GetConfiguationRoot();
var appContantsSection = root.GetSection("AppSettings:Constants");
var envContantsSection = appContantsSection.GetSection("HOST-ENVIROMENT-VARIABLE");
Dictionary appContants = new();
value.RegexGroupMatch(@"\{\{(.*?)\}\}", (m) =>
{
try
{
string appValue = appContantsSection.GetValue(m.Value);
string envValueKey = envContantsSection.GetValue(m.Value);
string preferEnvKey = envContantsSection.GetValue("!" + m.Value);
string replaceValue = (preferEnvKey == null ? null : GetEnvironmentVariable(preferEnvKey)) ?? appValue ?? (envValueKey == null ? null : GetEnvironmentVariable(envValueKey));
if (replaceValue != null)
{
appContants[m.Value] = replaceValue;
}
}
catch { }
});
foreach (var kp in appContants)
{
value = value.Replace(kp.Key, kp.Value);
}
if (defaultValue == null)
{
return value.ConvertTo();
}
else
{
return value.ConvertTo(defaultValue);
}
}
///
/// Gets configuration value and auto substitute with constants.
///
///
/// The section.
/// The key.
/// The default value.
///
public static T GetConfigMapVariable(this IConfiguration section, string key, T defaultValue = default(T))
{
return ResolveConfigVariable(section, section.GetSection(key).Value, defaultValue);
}
///
/// Binds the specified section.
///
///
/// The section.
///
///
///
public static T Bind(this IConfigurationSection section)
{
try
{
if (section.Value != null)
return section.Value.ConvertTo();
if (typeof(T).HasInterface()
&& !typeof(T).HasInterface())
{
var values = section.GetChildren().Map(GetValue);
return values.ConvertTo();
}
}
catch (Exception ex)
{
var message = $"The {section.Key} setting had an invalid format. " +
$"The value \"{section.Value}\" could not be cast to type {typeof(T).FullName}";
throw new ConfigurationErrorsException(message, ex);
}
try
{
var to = typeof(T).CreateInstance();
section.Bind(to);
return (T)to;
}
catch (InvalidOperationException ex)
{
throw new ConfigurationErrorsException(ex.Message, ex);
}
}
///
/// Binds the specified section name.
///
///
/// The configuration.
/// Name of the section.
///
public static T Bind(this IConfiguration config, string sectionName = null) => Bind(config.GetSection(sectionName ?? typeof(T).Name));
///
/// Existses the specified key.
///
/// The section.
/// The key.
///
public static bool Exists(this IConfigurationSection section, string key) => section.GetChildren().Any(x => x.Key == key) || section.GetSection(key).Exists();
///
/// Existses the specified key.
///
/// The configuration.
/// The key.
///
public static bool Exists(this IConfiguration config, string key) => config.GetChildren().Any(x => x.Key == key) || config.GetSection(key).Exists();
private static void GetAllChildren(List list, IConfiguration config)
{
foreach(var item in config.GetChildren())
{
if (item is IConfigurationSection) list.Add(item);
GetAllChildren(list, item);
}
}
///
/// Gets all children.
///
/// The configuration.
///
public static IEnumerable GetAllChildren(this IConfiguration configuration)
{
List list = new();
GetAllChildren(list, configuration);
return list;
}
/// Gets the value.
/// The section.
///
///
///
static object GetValue(this IConfigurationSection section)
{
if (section == null)
return null;
if (section.Value != null)
return section.Value;
var children = section.GetChildren();
var first = children.FirstOrDefault();
if (first == null)
return null;
if (first.Key == "0")
{
var to = children.Select(GetValue).ToList();
if (to.Count > 0)
return to;
}
else
{
var to = new Dictionary();
foreach (var child in children)
{
to[child.Key] = GetValue(child);
}
if (to.Count > 0)
return to;
}
return null;
}
}
}