C# 从类中获取所有属性和子属性
我使用反射来获取类名,需要获取类的所有子属性以及所有子属性的属性 我遇到了一个递归问题,项目被添加到了错误的列表中 我的代码如下:C# 从类中获取所有属性和子属性,c#,reflection,C#,Reflection,我使用反射来获取类名,需要获取类的所有子属性以及所有子属性的属性 我遇到了一个递归问题,项目被添加到了错误的列表中 我的代码如下: private List<Member> GetMembers(object instance) { var memberList = new List<Member>(); var childMembers = new List<Member>(); foreach (var propertyInfo
private List<Member> GetMembers(object instance)
{
var memberList = new List<Member>();
var childMembers = new List<Member>();
foreach (var propertyInfo in instance.GetType().GetProperties())
{
var member = new Member
{
Name = propertyInfo.PropertyType.IsList() ? propertyInfo.Name + "[]" : propertyInfo.Name,
Type = SetPropertyType(propertyInfo.PropertyType),
};
if (propertyInfo.PropertyType.IsEnum)
{
member.Members = GetEnumValues(propertyInfo).ToArray();
}
if (propertyInfo.PropertyType.BaseType == typeof(ModelBase))
{
var childInstance = propertyInfo.GetValue(instance) ?? Activator.CreateInstance(propertyInfo.PropertyType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.ToArray();
}
if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>) ||
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
var itemType = propertyInfo.PropertyType.GetGenericArguments()[0];
var childInstance = Activator.CreateInstance(itemType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.Distinct().ToArray();
}
memberList.Add(member);
}
return memberList;
}
private List GetMembers(对象实例)
{
var memberList=新列表();
var childMembers=新列表();
foreach(实例.GetType().GetProperties()中的var propertyInfo)
{
var成员=新成员
{
Name=propertyInfo.PropertyType.IsList()?propertyInfo.Name+“[]”:propertyInfo.Name,
Type=SetPropertyType(propertyInfo.PropertyType),
};
if(propertyInfo.PropertyType.IsEnum)
{
member.Members=GetEnumValues(propertyInfo.ToArray();
}
if(propertyInfo.PropertyType.BaseType==typeof(ModelBase))
{
var childInstance=propertyInfo.GetValue(实例)??Activator.CreateInstance(propertyInfo.PropertyType);
AddRange(GetMembers(childInstance));
member.Members=childMembers.ToArray();
}
if(propertyInfo.PropertyType.IsGenericType&&(propertyInfo.PropertyType.GetGenericTypeDefinition()==typeof(列表)||
propertyInfo.PropertyType.GetGenericTypeDefinition()==typeof(IList)))
{
var itemType=propertyInfo.PropertyType.GetGenericArguments()[0];
var childInstance=Activator.CreateInstance(itemType);
AddRange(GetMembers(childInstance));
member.Members=childMembers.Distinct().ToArray();
}
成员列表。添加(成员);
}
返回成员列表;
}
下面的方法行吗
public static IEnumerable<PropertyInfo> GetProperties(this Type type, int depth = 1)
{
IEnumerable<PropertyInfo> getProperties(Type currentType, int currentDepth)
{
if (currentDepth >= depth)
yield break;
foreach (var property in currentType.GetProperties())
{
yield return property;
foreach (var subProperty in getProperties(property.PropertyType,
currentDepth + 1))
{
yield return subProperty;
}
}
}
if (depth < 1)
throw new ArgumentOutOfRangeException(nameof(depth));
return getProperties(type, 0);
}
产量
Console.WriteLine(string.Join(Environment.NewLine,
typeof(Foo).GetProperties(2)
.Select(p => $"{p.DeclaringType.Name}: {p.Name}")));
将是:
Foo: S
String: Chars
String: Length
Foo: I
我不能肯定,因为我不知道你的代码调试和测试它的知识;但是,我相信您的问题可能是因为您正在使用
childMembers
列表。如果不是这样,请告诉我
private List<Member> GetMembers(object instance)
{
var memberList = new List<Member>();
foreach (var propertyInfo in instance.GetType().GetProperties())
{
var childMembers = new List<Member>(); // Moved to here, so it's not shared among all propertyInfo iterations.
var member = new Member
{
Name = propertyInfo.PropertyType.IsList() ? propertyInfo.Name + "[]" : propertyInfo.Name,
Type = SetPropertyType(propertyInfo.PropertyType),
};
if (propertyInfo.PropertyType.IsEnum)
{
member.Members = GetEnumValues(propertyInfo).ToArray();
}
if (propertyInfo.PropertyType.BaseType == typeof(ModelBase))
{
var childInstance = propertyInfo.GetValue(instance) ?? Activator.CreateInstance(propertyInfo.PropertyType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.ToArray();
}
if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>) ||
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
var itemType = propertyInfo.PropertyType.GetGenericArguments()[0];
var childInstance = Activator.CreateInstance(itemType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.Distinct().ToArray();
}
memberList.Add(member);
}
return memberList;
}
private List GetMembers(对象实例)
{
var memberList=新列表();
foreach(实例.GetType().GetProperties()中的var propertyInfo)
{
var childMembers=new List();//移动到此处,因此它不会在所有propertyInfo迭代中共享。
var成员=新成员
{
Name=propertyInfo.PropertyType.IsList()?propertyInfo.Name+“[]”:propertyInfo.Name,
Type=SetPropertyType(propertyInfo.PropertyType),
};
if(propertyInfo.PropertyType.IsEnum)
{
member.Members=GetEnumValues(propertyInfo.ToArray();
}
if(propertyInfo.PropertyType.BaseType==typeof(ModelBase))
{
var childInstance=propertyInfo.GetValue(实例)??Activator.CreateInstance(propertyInfo.PropertyType);
AddRange(GetMembers(childInstance));
member.Members=childMembers.ToArray();
}
if(propertyInfo.PropertyType.IsGenericType&&(propertyInfo.PropertyType.GetGenericTypeDefinition()==typeof(列表)||
propertyInfo.PropertyType.GetGenericTypeDefinition()==typeof(IList)))
{
var itemType=propertyInfo.PropertyType.GetGenericArguments()[0];
var childInstance=Activator.CreateInstance(itemType);
AddRange(GetMembers(childInstance));
member.Members=childMembers.Distinct().ToArray();
}
成员列表。添加(成员);
}
返回成员列表;
}
如果通过“将项目添加到错误列表”,您的意思是将一个成员的childMembers
添加到另一个成员,这可能是因为您正在重用childMembers
变量。将其移动到循环内,以实例化循环的每个交互。不需要childMembers
可以保存删除它并插入AddRange
justmember.Members=GetMembers(childInstance)。ToArray()
我没有提出这个建议,因为我不确定我有正确的OP解决方案,此外,为了简单起见,我试图使它尽可能接近OP的原始代码,但您是对的,它可以被删除:)
private List<Member> GetMembers(object instance)
{
var memberList = new List<Member>();
foreach (var propertyInfo in instance.GetType().GetProperties())
{
var childMembers = new List<Member>(); // Moved to here, so it's not shared among all propertyInfo iterations.
var member = new Member
{
Name = propertyInfo.PropertyType.IsList() ? propertyInfo.Name + "[]" : propertyInfo.Name,
Type = SetPropertyType(propertyInfo.PropertyType),
};
if (propertyInfo.PropertyType.IsEnum)
{
member.Members = GetEnumValues(propertyInfo).ToArray();
}
if (propertyInfo.PropertyType.BaseType == typeof(ModelBase))
{
var childInstance = propertyInfo.GetValue(instance) ?? Activator.CreateInstance(propertyInfo.PropertyType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.ToArray();
}
if (propertyInfo.PropertyType.IsGenericType && (propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(List<>) ||
propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(IList<>)))
{
var itemType = propertyInfo.PropertyType.GetGenericArguments()[0];
var childInstance = Activator.CreateInstance(itemType);
childMembers.AddRange(GetMembers(childInstance));
member.Members = childMembers.Distinct().ToArray();
}
memberList.Add(member);
}
return memberList;
}