public async Task <SectionView> GetSectionAsync(string name) { var section = await db.Sections.FirstOrDefaultAsync(x => x.Name.ToLower() == name.ToLower()); var sectionView = new SectionView(section); var configItemViews = new Dictionary <string, ConfigItemView>(); sectionView.Enums = new Dictionary <string, string[]>(); if (sectionTypes.SectionServerTypes.TryGetValue(section.Type, out Type sectionServerType)) { AddFields(sectionServerType); } if (sectionTypes.SectionClientTypes.TryGetValue(section.Type, out Type sectionClientType)) { AddFields(sectionClientType); } void AddFields(Type sectionType) { var dataObject = JsonSerializer.Deserialize(section.Options, sectionType); foreach (var propertyInfo in sectionType.GetProperties()) { ConfigItemAttribute configItemAttribute = propertyInfo.GetCustomAttribute <ConfigItemAttribute>(); var configItemView = new ConfigItemView { Name = propertyInfo.Name, Type = configItemAttribute.ConfigItemType.Name.Split(".")[^ 1].Replace("Item", "")
public static void SectionProcess(Section section, SectionTypes sectionTypes, ICheckRoles checkRoles) { section.Options = section.Options?.MakeJsonTextNotNull(); if (checkRoles != null) { section.Roles = checkRoles.CheckAndSetRoles(section.Roles); } var options = new Dictionary <string, object>(); if (sectionTypes.SectionServerTypes.TryGetValue(section.Type, out Type sectionServerType)) { AddFields(section.Options, sectionServerType, options); } if (sectionTypes.SectionClientTypes.TryGetValue(section.Type, out Type sectionClientType)) { AddFields(section.Options, sectionClientType, options); } section.Options = JsonSerializer.Serialize(options); void AddFields(string optionsJson, Type sectionType, Dictionary <string, object> optionsToAdd) { var dataObject = JsonSerializer.Deserialize(optionsJson, sectionType); var properties = sectionType.GetProperties(); foreach (var propertyInfo in properties) { ConfigItemAttribute configItemAttribute = propertyInfo.GetCustomAttribute <ConfigItemAttribute>(); string name = propertyInfo.Name; string typeName = configItemAttribute.ConfigItemType.Name.Split(".")[^ 1].Replace("Item", "");
static void Main(string[] args) { StringBuilder descriptionsBuilder = new StringBuilder(@"Configuration ************* "); StringBuilder exampleBuilder = new StringBuilder(@"Sample configuration (mainnet) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: [ "); foreach (string assemblyName in _assemblyNames) { Assembly assembly = Assembly.Load(new AssemblyName(assemblyName)); foreach (Type configType in assembly.GetTypes().Where(t => typeof(IConfig).IsAssignableFrom(t)).Where(t => !t.IsInterface)) { descriptionsBuilder.Append($@"{configType.Name} {string.Empty.PadLeft(configType.Name.Length, '^')} "); exampleBuilder.AppendLine(" {"); exampleBuilder.AppendLine($" \"ConfigModule\": \"{configType.Name}\""); exampleBuilder.AppendLine(" \"ConfigItems\": {"); var properties = configType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in properties) { exampleBuilder.AppendLine($" \"{propertyInfo.Name}\" : example"); ConfigItemAttribute attribute = propertyInfo.GetCustomAttribute <ConfigItemAttribute>(); if (attribute == null) { descriptionsBuilder.AppendLine($" - {propertyInfo.Name} - description missing").AppendLine(); continue; } descriptionsBuilder.AppendLine($" - {propertyInfo.Name} - {attribute.Description}").AppendLine(); } exampleBuilder.AppendLine(" }"); exampleBuilder.AppendLine(" },"); } } exampleBuilder.AppendLine(" ]"); string result = string.Concat(descriptionsBuilder.ToString(), exampleBuilder.ToString()); Console.WriteLine(result); Console.ReadLine(); File.WriteAllText("configuration.rst", result); }
private static void CheckDefault(PropertyInfo property, object instance) { ConfigItemAttribute attribute = property.GetCustomAttribute <ConfigItemAttribute>(); if (attribute == null) { //there are properties without attribute - we don't pay attention to them return; } string expectedValue = attribute.DefaultValue?.Trim('"') ?? "null"; string actualValue; object value = property.GetValue(instance); if (value == null) { actualValue = "null"; } else if (value is bool) { actualValue = value.ToString()?.ToLowerInvariant(); } else if (value is IList actualValueArray) { // there is a case when we have default value as [4, 8, 8] and we need to compare this string to int[] so removing brackets and whitespaces string[] expectedItems = expectedValue .Trim('[').Trim(']') .Replace(" ", "") .Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); int length = Math.Min(expectedItems.Length, actualValueArray.Count); for (int i = 0; i < length; i++) { string?actualValueAtIndex = actualValueArray[i]?.ToString(); string expectedValueAtIndex = expectedItems[i]; Assert.AreEqual(actualValueAtIndex, expectedValueAtIndex, $"Property: {property.Name}, expected value at index {i}: <{expectedValueAtIndex}> but was <{actualValueAtIndex}>"); } Assert.AreEqual(actualValueArray.Count, expectedItems.Length, $"Property: {property.Name}, expected value length: <{expectedItems.Length}> but was <{actualValueArray.Count}>"); return; } else { actualValue = value.ToString(); } Assert.AreEqual(actualValue, expectedValue, $"Property: {property.Name}, expected value: <{expectedValue}> but was <{actualValue}>"); }
public void All_default_values_are_correct(Type configType) { ConfigProvider configProvider = new ConfigProvider(); PropertyInfo[] properties = configType.GetProperties(); Type implementationType = configType.Assembly.GetTypes().SingleOrDefault(t => t.IsClass && configType.IsAssignableFrom(t)); object instance = Activator.CreateInstance(implementationType); foreach (PropertyInfo property in properties) { ConfigItemAttribute attribute = property.GetCustomAttribute <ConfigItemAttribute>(); if (attribute == null) { //there are properties without attribute - we don't pay attention to them continue; } string expectedValue = attribute.DefaultValue?.Trim('"') ?? "null"; string actualValue; object value = property.GetValue(instance); if (value == null) { actualValue = "null"; } else if (value is bool) { actualValue = value.ToString().ToLowerInvariant(); } else if (value is int[]) { //there is a case when we have default value as [4, 8, 8] and we need to compare this string to int[] so removing brackets and whitespaces int[] items = (int[])value; expectedValue = expectedValue.Trim('[').Trim(']'); expectedValue = expectedValue.Replace(" ", ""); string[] numbers = expectedValue.Split(','); for (int i = 0; i < numbers.Length; i++) { Assert.AreEqual(items[i].ToString(), numbers[i]); } continue; } else { actualValue = value.ToString(); } Assert.AreEqual(expectedValue, actualValue, $"Property: {property.Name}, expected value: <{expectedValue}> but was <{actualValue}>"); } }
private static void CheckDescribedOrHidden(PropertyInfo property, object instance) { ConfigItemAttribute attribute = property.GetCustomAttribute <ConfigItemAttribute>(); if (string.IsNullOrWhiteSpace(attribute?.Description) && !(attribute?.HiddenFromDocs ?? false)) { ConfigCategoryAttribute categoryLevel = property.DeclaringType?.GetCustomAttribute <ConfigCategoryAttribute>(); if (!(categoryLevel?.HiddenFromDocs ?? false)) { throw new AssertionException( $"Config {instance?.GetType().Name}.{property.Name} has no description and is in the docs."); } } }
private static void CheckDefault(PropertyInfo property, object instance) { ConfigItemAttribute attribute = property.GetCustomAttribute <ConfigItemAttribute>(); if (attribute == null) { //there are properties without attribute - we don't pay attention to them return; } string expectedValue = attribute.DefaultValue?.Trim('"') ?? "null"; string actualValue; object value = property.GetValue(instance); if (value == null) { actualValue = "null"; } else if (value is bool) { actualValue = value.ToString().ToLowerInvariant(); } else if (value is int[]) { //there is a case when we have default value as [4, 8, 8] and we need to compare this string to int[] so removing brackets and whitespaces int[] items = (int[])value; expectedValue = expectedValue.Trim('[').Trim(']'); expectedValue = expectedValue.Replace(" ", ""); string[] numbers = expectedValue.Split(','); for (int i = 0; i < numbers.Length; i++) { Assert.AreEqual(items[i].ToString(), numbers[i]); } return; } else { actualValue = value.ToString(); } Assert.AreEqual(expectedValue, actualValue, $"Property: {property.Name}, expected value: <{expectedValue}> but was <{actualValue}>"); }
public void Generate() { StringBuilder descriptionsBuilder = new StringBuilder(@"Configuration ************* Use '/' as the path separator so the configs can be shared between all platforms supported (Linux, Windows, MacOS). '--config', '--baseDbPath', and '--log' options are available from the command line to select config file, base DB directory prefix and log level respectively. "); StringBuilder exampleBuilder = new StringBuilder(@"Sample configuration (mainnet) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: [ "); List <(Type ConfigType, Type ConfigInterface)> configTypes = new List <(Type, Type)>(); foreach (string assemblyName in _assemblyNames) { Assembly assembly = Assembly.Load(new AssemblyName(assemblyName)); foreach (Type type in assembly.GetTypes().Where(t => typeof(IConfig).IsAssignableFrom(t)).Where(t => !t.IsInterface)) { var configInterface = type.GetInterfaces().Single(i => i != typeof(IConfig)); configTypes.Add((type, configInterface)); } } foreach ((Type configType, Type configInterface) in configTypes.OrderBy(t => t.ConfigType.Name)) { descriptionsBuilder.Append($@"{configType.Name} {string.Empty.PadLeft(configType.Name.Length, '^')} "); ConfigCategoryAttribute categoryAttribute = configInterface.GetCustomAttribute <ConfigCategoryAttribute>(); if (categoryAttribute != null) { descriptionsBuilder.AppendLine($"{categoryAttribute.Description}").AppendLine(); } exampleBuilder.AppendLine(" {"); exampleBuilder.AppendLine($" \"ConfigModule\": \"{configType.Name}\""); exampleBuilder.AppendLine(" \"ConfigItems\": {"); var properties = configType.GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in properties.OrderBy(p => p.Name)) { PropertyInfo interfaceProperty = configInterface.GetProperty(propertyInfo.Name); if (interfaceProperty == null) { Console.WriteLine($"Property {propertyInfo.Name} is missing from interface {configInterface.Name}."); } ConfigItemAttribute attribute = interfaceProperty.GetCustomAttribute <ConfigItemAttribute>(); string defaultValue = attribute == null ? "[MISSING_DOCS]" : attribute.DefaultValue; exampleBuilder.AppendLine($" \"{propertyInfo.Name}\" : {defaultValue},"); if (attribute == null) { descriptionsBuilder.AppendLine($" {propertyInfo.Name}").AppendLine(); continue; } descriptionsBuilder .AppendLine($" {propertyInfo.Name}") .AppendLine($" {attribute.Description}") .AppendLine($" default value: {defaultValue}") .AppendLine(); } if (exampleBuilder.Length > 0 && exampleBuilder[exampleBuilder.Length - 1] == ',') { exampleBuilder.Remove(exampleBuilder.Length - 1, 1); } exampleBuilder.AppendLine(" }"); exampleBuilder.AppendLine(" },"); } exampleBuilder.AppendLine(" ]"); string result = string.Concat(descriptionsBuilder.ToString(), exampleBuilder.ToString()); Console.WriteLine(result); File.WriteAllText("configuration.rst", result); File.WriteAllText("../../../docs/source/configuration.rst", result); }
private object GetTypeConfigItemValue(ConfigItem configItem, Type valType, object defVal, List <string> pathItemNames) { if (configItem == null) { LocalLoggingService.Warning("配置项为NULL,valType:{0},pathItemNames:{1}", valType, string.Join(",", pathItemNames.ToArray())); return(defVal); } if (ConfigHelper.IsUnderlyingType(valType)) { return(ConfigHelper.ChangeType(configItem.Value, valType, defVal)); } if (typeof(IList).IsAssignableFrom(valType)) { var genericArguments = valType.GetGenericArguments(); if (genericArguments.Length != 1 || !valType.IsGenericType) { return(null); } Type listItemType = genericArguments.First(); IList list = (IList)Activator.CreateInstance(valType); ConfigItem[] childConfigItems = InternalGetChildConfigItems(configItem.AppName, pathItemNames.ToArray()); if (childConfigItems == null || childConfigItems.Length == 0) { return(list); } foreach (ConfigItem childItem in childConfigItems) { listItemType = listItemType != typeof(object) ? listItemType : Type.GetType(childItem.ValueType); List <string> childPathItemNames = new List <string>(pathItemNames) { childItem.Name }; if (listItemType == null) { LocalLoggingService.Warning("listItemType 为NULL,childItem.ValueType:{0},pathItemNames:{1}", childItem.ValueType, string.Join(",", childPathItemNames.ToArray())); return(defVal); } object itemValue = GetTypeConfigItemValue(childItem, listItemType, listItemType == typeof(string) ? null : Activator.CreateInstance(listItemType), childPathItemNames); list.Add(itemValue); } return(list); } else if (typeof(IDictionary).IsAssignableFrom(valType)) { var genericArguments = valType.GetGenericArguments(); if (genericArguments.Length != 2 || genericArguments.First() != typeof(string) || !valType.IsGenericType) { return(null); } Type dicItemTypeOfValue = null; IDictionary dic = (IDictionary)Activator.CreateInstance(valType); ConfigItem[] childConfigItems = InternalGetChildConfigItems(configItem.AppName, pathItemNames.ToArray()); if (childConfigItems == null || childConfigItems.Length == 0) { return(dic); } foreach (ConfigItem childItem in childConfigItems) { dicItemTypeOfValue = genericArguments.Last(); dicItemTypeOfValue = dicItemTypeOfValue != typeof(object) ? dicItemTypeOfValue : Type.GetType(childItem.ValueType); List <string> childPathItemNames = new List <string>(pathItemNames) { childItem.Name }; if (dicItemTypeOfValue == null) { LocalLoggingService.Warning("dicItemTypeOfValue 为NULL,childItem.ValueType:{0},pathItemNames:{1}", childItem.ValueType, string.Join(",", childPathItemNames.ToArray())); return(defVal); } object itemValue = GetTypeConfigItemValue(childItem, dicItemTypeOfValue, dicItemTypeOfValue == typeof(string) ? null : Activator.CreateInstance(dicItemTypeOfValue), childPathItemNames); dic.Add(childItem.Name, itemValue); } return(dic); } else { FieldInfo[] fis = valType.GetFields(); foreach (FieldInfo fi in fis) { if (valType == fi.FieldType) { continue; } List <string> childPathItemNames = new List <string>(pathItemNames) { fi.Name }; ConfigItem childItem = InternalGetConfigItem(configItem.AppName, childPathItemNames.ToArray()); if (childItem == null) { ConfigItemAttribute configItemAttribute = fi.GetCustomAttributes(false).OfType <ConfigItemAttribute>().SingleOrDefault(); if (configItemAttribute == null) { configItemAttribute = new ConfigItemAttribute(); } string friendlyName = configItemAttribute.FriendlyName ?? fi.Name; string desc = configItemAttribute.Description; string value = null; if (ConfigHelper.IsUnderlyingType(fi.FieldType)) { if (fi.FieldType.IsEnum) { EnsureEnumTypeAdded(null, fi.FieldType); } value = fi.GetValue(defVal) != null ? (fi.GetValue(defVal)).ToString() : null; } childItem = InternalAddConfigItem(configItem.AppName, pathItemNames.ToArray(), fi.Name, friendlyName, desc, value, GetConfigItemSourceId(fi.FieldType), ConfigHelper.GetConfigItemValueType(fi.FieldType), ConfigHelper.GetConfigItemValueTypeEnum(fi.FieldType), ConfigHelper.IsCompositeValue(fi.FieldType)); } object itemValue = GetTypeConfigItemValue(childItem, fi.FieldType, ConfigHelper.IsUnderlyingType(fi.FieldType) ? fi.GetValue(defVal) : fi.GetValue(defVal) ?? Activator.CreateInstance(fi.FieldType), childPathItemNames); fi.SetValue(defVal, itemValue); } PropertyInfo[] pis = valType.GetProperties(); foreach (PropertyInfo pi in pis) { if (valType == pi.PropertyType) { continue; } List <string> childPathItemNames = new List <string>(pathItemNames) { pi.Name }; ConfigItem childItem = InternalGetConfigItem(configItem.AppName, childPathItemNames.ToArray()); if (childItem == null) { ConfigItemAttribute configItemAttribute = pi.GetCustomAttributes(false).OfType <ConfigItemAttribute>().SingleOrDefault(); if (configItemAttribute == null) { configItemAttribute = new ConfigItemAttribute(); } string friendlyName = configItemAttribute.FriendlyName ?? pi.Name; string desc = configItemAttribute.Description; string value = null; if (ConfigHelper.IsUnderlyingType(pi.PropertyType)) { if (pi.PropertyType.IsEnum) { EnsureEnumTypeAdded(null, pi.PropertyType); } value = pi.GetValue(defVal, null) != null ? (pi.GetValue(defVal, null)).ToString() : null; } childItem = InternalAddConfigItem(configItem.AppName, pathItemNames.ToArray(), pi.Name, friendlyName, desc, value, GetConfigItemSourceId(pi.PropertyType), ConfigHelper.GetConfigItemValueType(pi.PropertyType), ConfigHelper.GetConfigItemValueTypeEnum(pi.PropertyType), ConfigHelper.IsCompositeValue(pi.PropertyType)); } if (pi.CanWrite) { object itemValue = GetTypeConfigItemValue(childItem, pi.PropertyType, ConfigHelper.IsUnderlyingType(pi.PropertyType) ? pi.GetValue(defVal, null) : pi.GetValue(defVal, null) ?? Activator.CreateInstance(pi.PropertyType), childPathItemNames); pi.SetValue(defVal, itemValue, null); } } } return(defVal); }
private ConfigItem AddTypeConfigItem(bool isTopLevel, string appName, List <string> parentPathItemNames, string name, string friendlyName, string desc, Type valType, object defVal) { ConfigItemAttribute configItemAttribute; ConfigEntityAttribute configEntityAttribute; string value = null; if (ConfigHelper.IsUnderlyingType(valType)) { value = defVal != null?defVal.ToString() : null; } else if (isTopLevel) { configEntityAttribute = valType.GetCustomAttributes(false).OfType <ConfigEntityAttribute>().SingleOrDefault(); if (configEntityAttribute == null) { configEntityAttribute = new ConfigEntityAttribute(); } friendlyName = configEntityAttribute.FriendlyName ?? name; desc = configEntityAttribute.Description; } List <string> childPathItemnames = new List <string>(parentPathItemNames) { name }; ConfigItem configItem = InternalGetConfigItem(appName, childPathItemnames.ToArray()); if (configItem == null) { configItem = InternalAddConfigItem(appName, parentPathItemNames.ToArray(), name, friendlyName, desc, value, GetConfigItemSourceId(valType), ConfigHelper.GetConfigItemValueType(valType), ConfigHelper.GetConfigItemValueTypeEnum(valType), ConfigHelper.IsCompositeValue(valType)); } if (ConfigHelper.IsUnderlyingType(valType)) { if (valType.IsEnum) { EnsureEnumTypeAdded(null, valType); } return(configItem); } List <string> pathItemNames = new List <string>(parentPathItemNames) { configItem.Name }; if (typeof(IList).IsAssignableFrom(valType)) { var genericArguments = valType.GetGenericArguments(); if (genericArguments.Length != 1 || !valType.IsGenericType) { return(configItem); } Type listItemType = genericArguments.First(); int listIndex = 0; IList defListVal = (IList)defVal; if (defListVal != null && !configItem.ItemsInited) { foreach (object listItem in defListVal) { listItemType = listItem.GetType(); name = string.Format("{0}_{1}", configItem.Name, listIndex++); AddTypeConfigItem(false, appName, pathItemNames, name, name, null, listItemType, listItem); } ConfigServer.SetItemsInited(appName, pathItemNames.ToArray()); } } else if (typeof(IDictionary).IsAssignableFrom(valType)) { var genericArguments = valType.GetGenericArguments(); if (genericArguments.Length != 2 || genericArguments.First() != typeof(string) || !valType.IsGenericType) { return(configItem); } Type dicItemTypeOfValue = genericArguments.Last(); IDictionary defDicVal = (IDictionary)defVal; if (defDicVal != null && !configItem.ItemsInited) { foreach (DictionaryEntry dicItem in defDicVal) { dicItemTypeOfValue = dicItem.Value.GetType(); name = string.Format("{0}", dicItem.Key); AddTypeConfigItem(false, appName, pathItemNames, name, name, null, dicItemTypeOfValue, dicItem.Value); } ConfigServer.SetItemsInited(appName, pathItemNames.ToArray()); } } else { FieldInfo[] fis = valType.GetFields(); foreach (FieldInfo fi in fis) { if (valType == fi.FieldType) { continue; } configItemAttribute = fi.GetCustomAttributes(false).OfType <ConfigItemAttribute>().SingleOrDefault(); if (configItemAttribute == null) { configItemAttribute = new ConfigItemAttribute(); } friendlyName = configItemAttribute.FriendlyName ?? fi.Name; desc = configItemAttribute.Description; AddTypeConfigItem(false, appName, pathItemNames, fi.Name, friendlyName, desc, fi.FieldType, ConfigHelper.IsUnderlyingType(fi.FieldType) ? fi.GetValue(defVal) : fi.GetValue(defVal) ?? Activator.CreateInstance(fi.FieldType)); } PropertyInfo[] pis = valType.GetProperties(); foreach (PropertyInfo pi in pis) { if (valType == pi.PropertyType) { continue; } configItemAttribute = pi.GetCustomAttributes(false).OfType <ConfigItemAttribute>().SingleOrDefault(); if (configItemAttribute == null) { configItemAttribute = new ConfigItemAttribute(); } friendlyName = configItemAttribute.FriendlyName ?? pi.Name; desc = configItemAttribute.Description; AddTypeConfigItem(false, appName, pathItemNames, pi.Name, friendlyName, desc, pi.PropertyType, ConfigHelper.IsUnderlyingType(pi.PropertyType) ? pi.GetValue(defVal, null) : pi.GetValue(defVal, null) ?? Activator.CreateInstance(pi.PropertyType)); } } return(configItem); }