有沒有一種簡單的方法來挖掘對象並通過其哈希碼找到屬性或字段?這可以是嵌套屬性或集合中的值。我想問的原因是,我偶爾會看起來像WPF警告:如何通過哈希碼查找對象?
System.Windows.ResourceDictionary Warning: 9 : Resource not found;
ResourceKey='#FF000000'; ResourceKey.HashCode='51639504';
ResourceKey.Type='System.Windows.Media.SolidColorBrush'
警告並不總是出現,我有困難的時候跟蹤下來。我想,如果我知道哪個對象有散列碼,我可以更接近於解決這個問題。舉例來說,如果我有這個對象:
var first = new { a = 1, b = 2, d = new { aa = 11, bb = 22 } };
,並呼籲這個就可以了:
string str = FindHashCode(first, 22);
的結果將是:
"Anon > d > bb.hashcode = 22"
或類似的東西。 (我現在忽略散列碼衝突)
編輯:下面是我將基於@ Alberto的回答使用的內容。它搜索字段和屬性,無論是公開的還是非公開的。它包括對IEnumerables(列表,數組等)的支持,更具體地說是支持IDictionaries。它也處理散列碼衝突。如果兩個對象具有相同的散列碼,則StringBuilder將爲每個對象都有一個單獨的行。
using System.Reflection;
static string FindHashCode(object o, int hashCode)
{
StringBuilder strb = new StringBuilder();
FindHashCode(o, hashCode, o.GetType().Name, strb);
return strb.ToString().Trim();
}
static void FindHashCode(object o, int hashCode, string path, StringBuilder strb)
{
if (o.GetHashCode() == hashCode)
{
strb.AppendLine(path + ".hashcode = " + hashCode);
}
foreach (var field in GetFieldInfo(o))
{
if (field.Item1 == null || object.ReferenceEquals(o, field.Item1))
continue;
Type type = field.Item1.GetType();
if (type.IsPrimitive)
{
if(field.Item1.GetHashCode() == hashCode)
strb.AppendLine(path + " > " + field.Item2 + ".hashcode = " + hashCode);
}
else
{
FindHashCode(field.Item1, hashCode, path + " > " + field.Item2, strb);
}
}
}
static IEnumerable<Tuple<object, string>> GetFieldInfo(object arg)
{
var ienum = arg as System.Collections.IEnumerable;
var idict = arg as System.Collections.IDictionary;
if (ienum == null && idict == null)
{
BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
Type type = arg.GetType();
var list = type.GetFields(bf).Select(s => new Tuple<object, string>(s.GetValue(arg), s.Name)).Concat(
type.GetProperties(bf).Select(s => new Tuple<object, string>(s.GetValue(arg, null), s.Name)));
foreach (var item in list)
{
yield return item;
}
}
else if (idict != null)
{
foreach (System.Collections.DictionaryEntry item in idict)
{
yield return new Tuple<object, string>(item.Key, string.Format("Dict[{0}].Key", item.Key));
yield return new Tuple<object, string>(item.Value, string.Format("Dict[{0}].Value", item.Key));
}
}
//note that dictionaries implement IEnumerable
else if (ienum != null && !(ienum is string))
{
int count = 0;
foreach (var item in ienum)
{
yield return new Tuple<object, string>(item, string.Format("this[{0}]", count));
count++;
}
}
}
幾個對象可能具有相同的哈希碼,所以有不作爲「對應」的散列碼的對象這樣的事情。 –
我現在忽略散列碼碰撞 – user2023861