迭代通过反射获得的字典
本文关键字:字典 反射 迭代 | 更新日期: 2023-09-27 18:15:20
我有这段代码,它应该递归地打印给定对象的所有属性和它们的内容。
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
基本就是你的keyType
&valueType
是Type
类型的变量,在运行时已知,因此必须使用反射将propValue
转换为适当的泛型字典。但是,为了向后兼容,您可以使用Dictionary<TKey,TValue>
实现非泛型IDictionary
接口的事实。
所以在你的特殊情况下,替换这个就足够了:
foreach (KeyValuePair<keyType, valueType> kvp in (Dictionary<keyType, valueType>)propValue)
与这个:foreach (DictionaryEntry kvp in (IDictionary)propValue)
在调用泛型方法时,您必须提供实际的类型名称(或从您自己的方法定义中传递泛型类型参数)-而不是Type
的实例。
正如decPL所指出的,您应该使用system . collections . dictionary。但是,您还应该更改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操作符来执行此操作。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);
}
}
}