簡體   English   中英

遍歷通過反射獲得的字典

[英]Iterating over dictionary obtained through reflection

因此,我有這段代碼應該遞歸地打印給定對象的所有屬性及其內容。

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);
        }
    }
}

它不適用於ListDictionary ,我現在正在研究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實例。

基本上, keyTypevalueTypeType變量,在運行時是已知的,因此您必須使用反射將propValue轉換為適當的通用Dictionary。 但是,您可以使用以下事實:為了向后兼容, 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);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM