private void Init() { //use path defined in attribute if specified if (Attribute.GetCustomAttribute(_type, typeof(SettingPathAttribute)) is SettingPathAttribute pathAttribute) { _sectionPath = pathAttribute.Path; } //use typename if nothing is specified else { _sectionPath = _type.Name; } //read current values from IConfiguration if (string.IsNullOrWhiteSpace(_sectionPath)) { _configRoot.Bind(this); } else { _configRoot.GetSection(_sectionPath).Bind(this); } //ApplyReadTransformations foreach (var transformation in _options.StringTransformations) { StringTransformerBase.TransformObject(this, _configRoot, transformation.PerformReadTransformation); } }
/// <summary> /// Save this Configuration. /// SettingsSaveDirectory should be defined if no filePath is given. /// </summary> public string Save() { //decide for a filePath var filePath = _type.GetSavePathForSetting(_options); //ApplyWriteTransformations in reverse order var transformations = _options.StringTransformations; transformations.Reverse(); foreach (var transformation in transformations) { StringTransformerBase.TransformObject(this, _configRoot, transformation.PerformWriteTransformation); } //save the stuff var obj = JObject.FromObject(this); //use defined path if not root if (!string.IsNullOrWhiteSpace(_sectionPath)) { obj = _sectionPath.Split(':') .Reverse() .Aggregate(obj, (current, section) => new JObject { { section, current } }); } File.WriteAllText(filePath, obj.ToString()); return(filePath); }
/// <summary> /// Export this configuration based on root level to a given file path /// given folder must already exist /// </summary> /// <param name="filePath">file path to export to</param> public void Save(string filePath) { var type = GetType(); var copyForSave = MemberwiseClone(); //decide for a SectionPath var sectionPath = type.GetSectionPath(); //ApplyWriteTransformations in reverse order var transformations = ConfigurationOptions.StringTransformations.ToList(); transformations.Reverse(); foreach (var transformation in transformations) { StringTransformerBase.TransformObject(copyForSave, ConfigurationRoot, transformation.PerformWriteTransformation); } //save the stuff var obj = JObject.FromObject(copyForSave); //use defined path if not root if (!string.IsNullOrWhiteSpace(sectionPath)) { obj = sectionPath.Split(':') .Reverse() .Aggregate(obj, (current, section) => new JObject { { section, current } }); } File.WriteAllText(filePath, obj.ToString()); }
private void Init() { //problems: //a: if multiple providers provide values for a collection, the values get added //doubleMerge: when having Config inside Config, Bind will be executed twice // Bind binds recursive, so the subConfig Constructor calls Init (bind#1) and then binds again below (bind#2) //c: On the init call from Change token, existing element will be bound again //d: setting classes will be registered as singletons, but when using sub settings is used, // you will end up with separate instances despite registrations. To handle this correctly, // sub settings would need to be resolved from ioc, and set in this instance. #region doubleMerge //create sub Settings by us here, so they will not get double bound here //after binding below, the constructor of the sub class will bind, and then the binding here will bind it again //so with merge behaviour of binding, values of array will be doubled //https://github.com/dotnet/runtime/issues/46988 //idea for doubleMerge workaround: // construct sub configs before binding (has correct values) and replace here after binding. var subSettings = new Dictionary <PropertyInfo, object>(); foreach (var propertyInfo in GetType().GetProperties() .Where(x => x.CanRead && x.CanWrite) .Where(x => typeof(SettingsBase).IsAssignableFrom(x.PropertyType))) { var subSetting = Activator.CreateInstance(propertyInfo.PropertyType); subSettings.Add(propertyInfo, subSetting); } #endregion var sectionPath = GetType().GetSectionPath(); //read current values from IConfiguration if (string.IsNullOrWhiteSpace(sectionPath)) { ConfigurationRoot.Bind(this); } else { ConfigurationRoot.GetSection(sectionPath).Bind(this); } //ApplyReadTransformations foreach (var transformation in ConfigurationOptions.StringTransformations) { StringTransformerBase.TransformObject(this, ConfigurationRoot, transformation.PerformReadTransformation); } #region doubleMerge //set back sub settings foreach (var pair in subSettings) { pair.Key.SetValue(this, pair.Value); } #endregion }