using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Porta.Kundenzähler.Services.Extension { public static class ConfigurationExtension { #region Configuration reading /// /// Read a section of the configuration and bind it to a corresponding object containing the same properties (Names must match) /// /// The type of the config section object. /// The full configuration. /// The key of the section. /// The config section object. public static T GetSection(this IConfiguration configuration, string key) { if (String.IsNullOrEmpty(key)) throw new ArgumentException("The section key must not be NULL or empty.", key); // Create empty instance of config object type var optionsObj = Activator.CreateInstance(); var section = configuration.GetSection(key); if (section == null) throw new ArgumentException("The requested section cannot be found in configuration file.", key); // Map the object properties to the section properties MapSectionPropertiesToObject(configuration, optionsObj, section); return optionsObj; } /// /// Map the properties of a configuration object to the corresponding properties in the configuration section /// /// The full configuration. /// The current options object. /// The current processing section. private static void MapSectionPropertiesToObject(IConfiguration configuration, object optionsObj, IConfigurationSection currentSection) { // Get all options object properties var properties = optionsObj.GetType().GetProperties(); foreach (var propertyInfo in properties) { // Check non primitive, not value typed, only classed properties if (propertyInfo.PropertyType.IsClass && !propertyInfo.PropertyType.IsArray && !propertyInfo.PropertyType.IsValueType && !propertyInfo.PropertyType.IsPrimitive && propertyInfo.PropertyType.FullName != "System.String") { // Get the section configuration value of the current property var valueObj = currentSection.GetValue(propertyInfo.Name); // Proceed when value object can be created if (valueObj != null) { // If the property is NULL, create an object for the property if (propertyInfo.GetValue(optionsObj) == null) propertyInfo.SetValue(optionsObj, Activator.CreateInstance(propertyInfo.PropertyType)); // Recursive call MapSectionPropertiesToObject(configuration, propertyInfo.GetValue(optionsObj), currentSection.GetSection(propertyInfo.Name)); } } else { // Read the value from the current section var valueObj = currentSection.GetValue(propertyInfo.Name); // If the value object is NULL then it might not be set or cannot be evaluated if (valueObj != null) { // Serialize the value as a JSON string var jsonStr = JsonConvert.SerializeObject(valueObj); // Deserialize from the JSON string to prevent conversion issues var value = JsonConvert.DeserializeObject(jsonStr, propertyInfo.PropertyType); propertyInfo.SetValue(optionsObj, value); } } } } #endregion } }