Skip to content

Commit ab875ea

Browse files
committed
Improves property discovery using reflection
Replaces JSON-based property enumeration with reflection to ensure all public properties are documented, including those with DefaultValueHandling.Ignore. Adds helper method to safely extract property values and handle complex objects gracefully during documentation generation.
1 parent b643971 commit ab875ea

File tree

1 file changed

+52
-11
lines changed

1 file changed

+52
-11
lines changed

src/MigrationTools.ConsoleDataGenerator/ClassDataLoader.cs

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using MigrationTools.Options;
44
using Newtonsoft.Json;
55
using Newtonsoft.Json.Linq;
6+
using System.Reflection;
67

78
namespace MigrationTools.ConsoleDataGenerator
89
{
@@ -121,22 +122,62 @@ private ClassData CreateClassDataFromOptions<TOptionsInterface>(List<Type> allTy
121122
private List<OptionsItem> populateOptions(object item, JObject joptions)
122123
{
123124
List<OptionsItem> options = new List<OptionsItem>();
124-
if (!(joptions is null))
125+
126+
// Use reflection to get all public properties, not just those in the JSON serialization
127+
// This ensures properties with DefaultValueHandling.Ignore are still documented
128+
var properties = item.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance)
129+
.Where(p => p.CanRead && p.CanWrite)
130+
.OrderBy(p => p.Name);
131+
132+
foreach (var property in properties)
125133
{
126-
var jpropertys = joptions.Properties().OrderBy(t => t.Name);
127-
foreach (JProperty jproperty in jpropertys)
128-
{
129-
OptionsItem optionsItem = new OptionsItem();
130-
optionsItem.ParameterName = jproperty.Name;
131-
optionsItem.Type = codeDocs.GetPropertyType(item, jproperty);
132-
optionsItem.Description = codeDocs.GetPropertyData(item, joptions, jproperty, "summary");
133-
optionsItem.DefaultValue = codeDocs.GetPropertyData(item, joptions, jproperty, "default");
134-
options.Add(optionsItem);
135-
}
134+
// Get the property value and handle complex objects appropriately for JProperty
135+
var propertyValue = GetSimplePropertyValue(property, item);
136+
137+
// Create a temporary JProperty for compatibility with existing code documentation methods
138+
var tempJProperty = new JProperty(property.Name, propertyValue);
139+
140+
OptionsItem optionsItem = new OptionsItem();
141+
optionsItem.ParameterName = property.Name;
142+
optionsItem.Type = property.PropertyType.Name.Replace("`1", "").Replace("`2", "").Replace("`", "");
143+
optionsItem.Description = codeDocs.GetPropertyData(item.GetType(), joptions, tempJProperty, "summary");
144+
optionsItem.DefaultValue = codeDocs.GetPropertyData(item.GetType(), joptions, tempJProperty, "default");
145+
options.Add(optionsItem);
136146
}
147+
137148
return options;
138149
}
139150

151+
private object GetSimplePropertyValue(System.Reflection.PropertyInfo property, object instance)
152+
{
153+
try
154+
{
155+
var value = property.GetValue(instance);
156+
157+
// Handle complex objects by returning a simple representation
158+
if (value == null)
159+
return null;
160+
161+
// For simple types, return the value as is
162+
if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(string) || property.PropertyType == typeof(DateTime) || property.PropertyType.IsEnum)
163+
return value;
164+
165+
// For complex objects, return a simple string representation to avoid JSON serialization issues
166+
return value.ToString();
167+
}
168+
catch
169+
{
170+
// Return a default value for the property type if we can't get the actual value
171+
if (property.PropertyType == typeof(string))
172+
return "";
173+
if (property.PropertyType == typeof(bool))
174+
return false;
175+
if (property.PropertyType.IsValueType)
176+
return Activator.CreateInstance(property.PropertyType);
177+
return null;
178+
}
179+
}
180+
140181
static string ConvertSectionWithPathToJson(IConfiguration configuration, IConfigurationSection section, IOptions option = null)
141182
{
142183
var pathSegments = option == null ? section.Path.Split(':') : option.ConfigurationMetadata.PathToInstance.Split(':');

0 commit comments

Comments
 (0)