我在做一些类似递归获取属性的事情
代码的问题是:它只下降了一级,我想知道如何使用反射自动获取所有属性?我刚刚编写了以下示例容器代码:
public class Container
{
public Bottle MyBottle { get; set; }
public List<Address> Addresses { get; set; }
public Container()
{
Address a = new Address();
a.AddressLine1 = "1 Main St";
a.AddressLine2 = "2 Main St";
Addresses = new List<Address>();
Addresses.Add(a);
MyBottle = new Bottle();
MyBottle.BottleName = "Big bottle";
MyBottle.BottageAge = 2;
}
}
public class Bottle
{
public string BottleName { get; set; }
public int BottageAge { get; set; }
}
public class Address
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public List<SpecialFolder> SpecialFolders { get; set; }
public Address()
{
SpecialFolders = new List<SpecialFolder>();
SpecialFolder sf = new SpecialFolder();
sf.TemplateFolder = Environment.SpecialFolder.Templates.ToString();
sf.UserFolder = Environment.SpecialFolder.UserProfile.ToString();
SpecialFolders.Add(sf);
}
}
public class SpecialFolder
{
public string TemplateFolder { get; set; }
public string UserFolder { get; set; }
}
在主要方法中:
static void Main(string[] args)
{
Container c = new Container();
PrintProperties(c);
}
public static void PrintProperties(object obj)
{
PrintProperties(obj, 0);
}
public static void PrintProperties(object obj, int indent)
{
if (obj == null) return;
string indentString = new string(' ', indent);
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
if (property.PropertyType.Assembly == objType.Assembly)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
else
{
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
我希望得到:
MyBottle:
BottleName: Big bottle
BottageAge: 2
Addresses:
AddressLine1: 1 Main St
AddressLine2: 2 Main St
SpecialFolders:
TemplateFolder: Templates
UserFolder: UserProfile
我现在得到的结果是:
MyBottle:
BottleName: Big bottle
BottageAge: 2
Addresses: System.Collections.Generic.List`1[TreeViewReflectionExample.Address]
有人能帮我使用PrintProperties方法吗?非常感谢你。
根据康拉德·科科萨的回答:
private string ObjectToString(object obj, int indent = 0)
{
if (obj is null)
{
return "";
}
var sb = new StringBuilder();
string indentString = new string(' ', indent);
Type objType = obj.GetType();
foreach (PropertyInfo property in objType.GetProperties())
{
object propValue = property.GetValue(obj);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
sb.Append($"{indentString}- {property.Name}\n");
sb.Append(ObjectToString(item, indent + 4));
}
}
else if (property.Name != "ExtensionData")
{
sb.Append($"{indentString}- {property.Name}={propValue}\n");
if (property.PropertyType.Assembly == objType.Assembly)
{
sb.Append(ObjectToString(propValue, indent + 4));
}
}
}
return sb.ToString();
}
更新
基于以下旧问题编辑代码:在枚举字符串的属性时TargetParameterCountException
private string ObjectToString(object obj, int indent = 0)
{
var sb = new StringBuilder();
if (obj != null)
{
string indentString = new string(' ', indent);
if (obj is string)
{
sb.Append($"{indentString}- {obj}\n");
}
else if (obj is Array)
{
var elems = obj as IList;
sb.Append($"{indentString}- [{elems.Count}] :\n");
for (int i = 0; i < elems.Count; i++)
{
sb.Append(ObjectToString(elems[i], indent + 4));
}
}
else
{
Type objType = obj.GetType();
PropertyInfo[] props = objType.GetProperties();
foreach (PropertyInfo prop in props)
{
if (prop.GetIndexParameters().Length == 0)
{
object propValue = prop.GetValue(obj);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
sb.Append($"{indentString}- {prop.Name} :\n");
sb.Append(ObjectToString(item, indent + 4));
}
}
else if (prop.Name != "ExtensionData")
{
sb.Append($"{indentString}- {prop.Name} = {propValue}\n");
if (prop.PropertyType.Assembly == objType.Assembly)
{
sb.Append(ObjectToString(propValue, indent + 4));
}
}
}
else
{
sb.Append($"{indentString}- {prop.Name} ({prop.PropertyType.Name}): <Indexed>\n");
}
}
}
}
return sb.ToString();
}
更新2
public static string ObjectToString(object obj, int indent = 0)
{
var sb = new StringBuilder();
if (obj != null)
{
string indentString = new string(' ', indent);
if (obj is string || obj.IsNumber())
{
sb.Append($"{indentString}- {obj}\n");
}
else if (obj.GetType().BaseType == typeof(Enum))
{
sb.Append($"{indentString}- {obj.ToString()}\n");
}
else if (obj is Array)
{
var elems = obj as IList;
sb.Append($"{indentString}- [{elems.Count}] :\n");
for (int i = 0; i < elems.Count; i++)
{
sb.Append(ObjectToString(elems[i], indent + 4));
}
}
else
{
Type objType = obj.GetType();
PropertyInfo[] props = objType.GetProperties();
foreach (PropertyInfo prop in props)
{
if (prop.GetIndexParameters().Length == 0)
{
object propValue = prop.GetValue(obj);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
sb.Append($"{indentString}- {prop.Name} :\n");
sb.Append(ObjectToString(item, indent + 4));
}
}
else if (prop.Name != "ExtensionData")
{
sb.Append($"{indentString}- {prop.Name} = {propValue}\n");
if (prop.PropertyType.Assembly == objType.Assembly)
{
sb.Append(ObjectToString(propValue, indent + 4));
}
}
}
else if (objType.GetProperty("Item") != null)
{
int count = -1;
if (objType.GetProperty("Count") != null &&
objType.GetProperty("Count").PropertyType == typeof(int))
{
count = (int)objType.GetProperty("Count").GetValue(obj, null);
}
for (int i = 0; i < count; i++)
{
object val = prop.GetValue(obj, new object[] { i });
sb.Append(ObjectToString(val, indent + 4));
}
}
}
}
}
return sb.ToString();
}
public static bool IsNumber(this object value)
{
return value is sbyte
|| value is byte
|| value is short
|| value is ushort
|| value is int
|| value is uint
|| value is long
|| value is ulong
|| value is float
|| value is double
|| value is decimal;
}
您希望分别处理基元类型和字符串,并循环遍历枚举,而不仅仅是获取它们的ToString()值。因此,您的代码可以更新为:
public void PrintProperties(object obj, int indent)
{
if (obj == null) return;
string indentString = new string(' ', indent);
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
if(property.PropertyType.IsPrimitive || property.PropertyType == typeof(string))
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
else if (typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
IEnumerable enumerable = (IEnumerable)propValue;
foreach(object child in enumerable)
PrintProperties(child, indent + 2);
}
else
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
}
}
您的代码有两个问题:
if(property.PropertyType.Assembly==objType.Assembly)
的原因,您将忽略系统。集合
like列表
例如,您可以将其更改为:
public void PrintProperties(object obj, int indent)
{
if (obj == null) return;
string indentString = new string(' ', indent);
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
var elems = propValue as IList;
if (elems != null)
{
foreach (var item in elems)
{
PrintProperties(item, indent + 3);
}
}
else
{
// This will not cut-off System.Collections because of the first check
if (property.PropertyType.Assembly == objType.Assembly)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
else
{
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
}
问题内容: 使用MySQL,我想从具有此类字段结构的表中返回父母列表。ID,PARENTID,NAME(标准的父子层次结构)。我想遍历树以返回所有“父母”的列表。 我意识到“嵌套集”可能是处理此问题的更好方法-但目前我无法更改数据的结构。我将来会希望这样做。当前-我的数据集实际上将包含一些深度级别- 没什么疯狂的……也许2-5,所以我的递归命中不应太“昂贵”。 我已经看过SQL Server获取父
问题内容: 我有以下查询和方法 与作为 我希望这个查询可以获取and >关系,但事实并非如此。假设I查询有两个运算符,Hibernate将执行1 + 2 * 2 = 5个查询 我猜这是因为我加入了operator 元素,但他们必须加入自己的行列。 我可以执行同时执行的HQL查询吗? 问题答案: 如果您知道树中只有两个级别,那么您是否考虑过加入更深的一个级别。像下面的东西?
问题内容: 我有一个Comment表,其中有一个CommentID和ParentCommentID。我正在尝试获取评论的所有子级的列表。到目前为止,这是我到目前为止尚未完成的测试。 2个问题: 有什么明显的方法可以改善这一点吗?(此外,也许还可以使用CTE在sql中创建视图。) 我怎么不能只给一个IEnumerable屈服呢? 无论如何,在这种情况下可以使用SelectMany吗? 问题答案: 我
问题内容: 我有一张桌子 我填写这个表 选择idFolder = 1的文件夹时,应返回该文件夹和子子文件夹的所有子文件夹(2,3,4,5,6,7) 当我选择文件夹ID = 4 ==>(5,7,6) 当我选择文件夹ID = 3 ==>(4,5,6,7) 一个查询该怎么做? 谢谢 问题答案: 这是工作中的一个 在此处查看SQL固件:http://sqlfiddle.com/#!2 / 02b78 /
我的应用程序中有一个名为posts的实体。帖子可以是其他帖子的子帖子,因此父帖子有hasMany('Posts'),子帖子有hasOne('post')。包含是无限的。 以下是模式: 如何递归地获取“Post_id”设置为null的第一篇帖子的所有子帖子和子帖子的子帖子等? 请不要在这里评论性能,我知道这样的模式很糟糕,我只想知道如何正确编写递归函数来检索无限嵌套的帖子。
问题内容: 这是我想要做的事情:-我需要一个函数,当将其作为参数传递时,ID(用于事物类别)将提供所有子类别,子子类别和子子子..etc 。-我在考虑使用递归函数,因为我不知道子类别及其子类别的数量,依此类推,这是到目前为止我一直在尝试的操作 如果我使用return而不是echo,我将不会得到相同的结果。我需要一些帮助以解决此问题或从头开始重写它 问题答案: 我很难弄清楚你的职能。我认为这会做您想