谈到你的问题,我们可以用教学的方式回答,并排除任何现有序列化架构。这样一来,您将完全自由地进入对象引用树,不需要使用反射就能填充结果字典。
我们需要一个简单的方法来访问给定的对象,然后对于每个公共属性递归调用它本身。签名应包括一个字符串,表示当前父链(例如:
"Property1.InnerProperty4.InnerProperty7"
),返回类型应为一个
Dictionary<string,string>
,只包含当前和嵌套对象中的内容。
在开始时,它应该检查参数是值类型还是非值类型,在前者的情况下,只需创建一个新字典,添加一个新的键值对(父+名称,值)并返回;而在后者的情况下,创建一个新字典,然后对于每个公共属性,调用它本身,传递当前属性,父+名称字符串,将返回的字典与之前创建的字典连接起来,在循环结束时返回这个大字典。我们可以在开头添加另一个条件,检查传递的对象是否实现了类似IEnumerable接口的东西。在这种情况下,不仅要遍历它的成员,还要遍历它的索引器,并为每个项调用该方法。
我抽出时间来实现了昨天描述的内容。这里有一个递归方法,旨在返回给定对象的(公共属性全名)-(值)对的字典。当然,它可能不完全符合您想要实现的细节,但您将发现很多技巧、思路和概念来组成自己的方法:
namespace MyNamespace
{
public class ClassA {
int p1 = 1;
string p2 = "abcdef";
List<string> p3 = new List<string>() { "ghi","lmn" };
ClassB p4 = new ClassB();
ClassB p5 = null;
public int PA1 { get { return p1; } }
public string PA2 { get { return p2; } }
public List<string> PA3 { get { return p3; } }
public ClassB PA4 { get { return p4; } }
public ClassB PA5 { get { return p5; } }
}
public class ClassB{
private string p1 = "zeta";
public string PB1 { get { return p1; } }
}
public class Program {
public void Main()
{
ClassA o = new ClassA();
Dictionary<string, string> result = GetPropertiesDeepRecursive(o, "[o]", new List<string>() { "MyNamespace" });
}
public Dictionary<string, string> GetPropertiesDeepRecursive(object o, string memberChain, List<string> includedNamespaces)
{
List<string> types_to_exclude_by_design = new List<string>() { "System.string", "System.String" };
Dictionary<string, string> r = new Dictionary<string, string>();
if (o == null)
{
r.Add(memberChain, "[null]");
return r;
}
Type type = o.GetType();
if (types_to_exclude_by_design.Contains(type.FullName))
{
r.Add(memberChain, o.ToString());
return r;
}
bool isEnumerable =
type
.GetInterfaces()
.Any(t => t == typeof(System.Collections.IEnumerable));
if (isEnumerable)
{
int i_item = 0;
foreach (object item in (System.Collections.IEnumerable)o)
{
string itemInnerMember = string.Format("{0}[{1}]", memberChain, i_item++);
r = r.Concat(GetPropertiesDeepRecursive(item, itemInnerMember, includedNamespaces)).ToDictionary(e => e.Key, e => e.Value);
}
return r;
}
if (!includedNamespaces.Contains(type.Namespace))
{
r.Add(memberChain, o.ToString());
return r;
}
PropertyInfo[] pList = type.GetProperties();
foreach (PropertyInfo p in pList)
{
object innerObject = p.GetValue(o, null);
string innerMember = string.Format("{0}.{1}", memberChain, p.Name);
r = r.Concat(GetPropertiesDeepRecursive(innerObject, innerMember, includedNamespaces)).ToDictionary(e => e.Key, e => e.Value);
}
return r;
}
}
}