迭代通过反射获得的字典
所以我有这个代码应该递归地打印给定对象的所有属性及其内容。迭代通过反射获得的字典
static 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.Assembly == objType.Assembly && !property.PropertyType.IsEnum)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
else
{
if (null != propValue)
{
Type t = propValue.GetType();
//Console.WriteLine(":::::{0}:::::", propValue.GetType());
bool isDict = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>);
if (isDict)
{
Type keyType = t.GetGenericArguments()[0];
Type valueType = t.GetGenericArguments()[1];
foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue)
{
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
}
}
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
它不适合List
和Dictionary
工作呢,我工作的一部分Dictionary
现在。
问题是,我提取键和值与类型:
Type keyType = t.GetGenericArguments()[0];
Type valueType = t.GetGenericArguments()[1];
但随后VS2013告诉我,有一个与此行的一个问题:
foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue)
它告诉我,未找到类型或名称空间KeyType和valueType。 我错过了什么?
谢谢。
PS:.NET 4.5.1
在调用泛型方法你必须提供实际类型的名称(或者通过从你自己的方法的定义泛型类型参数) - 不是Type
实例。
所以没有办法自动打印通过提取的字典的内容反射?因为在'propValue'中,我可以看到键和值的类型(例如:'System.Collections.Generic.Dictionary 2 [Mobile.Fonct ionComptage.Modele.IndexFournisseur,System.String]') –
基本上你keyType
& valueType
是Type
类型的变量,它在运行时已知的,所以你必须使用反射来投你propValue
到适当的通用词典。但是,您可以使用这样的事实:为了向后兼容,Dictionary<TKey,TValue>
实现了非通用IDictionary
接口。
因此,在特定情况下,将足以取代这个:
foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue)
与此:
foreach (DictionaryEntry kvp in (IDictionary)propValue)
由于decPL指出,你应该使用System.Collections.IDictionary。但是,你也应该改变你的isDict逻辑。 System.Type.IsAssignableFrom允许您检查“指定类型的实例是否可以分配给当前类型实例”。这里是显示它的行为的代码。
using System;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Testing System.Type.IsAssignableFrom");
var propValue = new Dictionary<string, string>() { { "hello", "world" } };
var t = propValue.GetType();
bool isDict = typeof(IDictionary).IsAssignableFrom(t);
if (isDict)
{
foreach (DictionaryEntry kvp in (IDictionary)propValue)
{
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
}
Console.ReadLine();
}
}
}
所以你的方法应该看起来像这样。
static 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.Assembly == objType.Assembly && !property.PropertyType.IsEnum)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
else
{
if (null != propValue)
{
Type t = propValue.GetType();
//Console.WriteLine(":::::{0}:::::", propValue.GetType());
bool isDict = typeof(IDictionary).IsAssignableFrom(t);
if (isDict)
{
foreach (DictionaryEntry kvp in (IDictionary)propValue)
{
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
}
}
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
但是,您也可以使用C#作为运算符来做到这一点。 as运算符将尝试执行到指定类型的转换。如果不可行,则返回null。一些示例代码。
using System;
using System.Collections;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Testing System.Type.IsAssignableFrom");
var propValue = new Dictionary<string, string>() { { "hello", "world" } };
IDictionary asDict = propValue as IDictionary;
if (asDict != null)
{
foreach (DictionaryEntry kvp in (IDictionary)propValue)
{
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
}
Console.ReadLine();
}
}
}
和你的方法。
static 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.Assembly == objType.Assembly && !property.PropertyType.IsEnum)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
else
{
if (null != propValue)
{
var asDict = propValue as IDictionary;
if (asDict != null)
{
foreach (DictionaryEntry kvp in asDict)
{
Console.WriteLine(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}
}
}
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
'keyType'&'valueType'在你的例子是Type'但'KeyValuePair的'实例中'需要一个类型名称,使得类型可以在运行时评估。您必须使用非泛型“Dictionary”类访问字典并手动投射键和值对象。 –
Howwie
[将C#中的所有对象转储到日志的最佳方式是什么?](http:// stackoverflow。com/questions/360277 /什么是最好的方式转储整个对象到一个登录在c) –