談到你的問題,我們可能會把答案放在教導的方式,只是排除任何存在的序列化架構。這樣你就可以完全自由地進入對象引用樹,而不用費力使用反射並填充結果字典。
我們需要一個簡單的方法來訪問給定的對象,然後爲每個公共屬性遞歸地調用它自己。簽名應該包含一個字符串,表示至少是當前的父鏈(例如:"Property1.InnerProperty4.InnerProperty7"
),返回類型應該是Dictionary<string,string>
,只有來自當前和嵌套對象的東西。 在開始時它應該檢查參數是否爲值類型,在前一種情況下只需創建一個新的字典,添加一個新的KeyValuePair(parent + name,value)並返回;而在後一種情況下,創建一個新的Dictionary,然後foreach公共屬性調用本身傳遞當前屬性,父+名稱字符串並將返回的字典與先前創建的字典連接起來,並在循環結束時返回此大字典。我們可以在開始時檢查傳遞的對象是否實現類似於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" });
}
/// <summary>
/// Returns a dictionary of propertyFullname-value pairs of the given object (and deep recursively for its public properties)
/// note: it's object oriented (on purpose) and NOT type oriented! so it will just return values of not null object trees
/// <param name="includedNamespaces">a list of full namespaces for whose types you want to deep search in the tree</param>
/// </summary>
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" };
//the results bag
Dictionary<string, string> r = new Dictionary<string, string>();
//if o is null just return value = [null]
if (o == null)
{
r.Add(memberChain, "[null]");
return r;
}
//the current object argument type
Type type = o.GetType();
//reserve a special treatment for specific types by design (like string -that's a list of chars and you don't want to iterate on its items)
if (types_to_exclude_by_design.Contains(type.FullName))
{
r.Add(memberChain, o.ToString());
return r;
}
//if the type implements the IEnumerable interface...
bool isEnumerable =
type
.GetInterfaces()
.Any(t => t == typeof(System.Collections.IEnumerable));
if (isEnumerable)
{
int i_item = 0;
//loop through the collection using the enumerator strategy and collect all items in the result bag
//note: if the collection is empty it will not return anything about its existence,
// because the method is supposed to catch value items not the list itself
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;
}
//here you need a strategy to exclude types you don't want to inspect deeper like int,string and so on
//in those cases the method will just return the value using the specific object.ToString() implementation
//now we are using a condition to include some specific types on deeper inspection and exclude all the rest
if (!includedNamespaces.Contains(type.Namespace))
{
r.Add(memberChain, o.ToString());
return r;
}
//otherwise go deeper in the object tree...
//and foreach object public property collect each value
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;
}
}
}
Diego,沒關係。我之前做過這個,但是我失去了那個代碼。在MVC庫中的某個人必須實現這一點。如果可能的話,我想抓取並重用。所以是的,我只是問在已經寫好的大型互聯網中是否有可用的解決方案。我可以重新實施它沒有問題,但有點按時間。 – Alwyn 2012-07-25 01:34:44
哦,你真的不該有的人。我期待有人把我指向一個不是從頭開始構建的MVC類庫。但是這超出了這一點 - 非常感謝。 – Alwyn 2012-07-25 14:14:21