Cómo obtener un System.Collections.Generic.List < FieldInfo > ¿Qué contiene todos los FieldInfo de un objeto de un Tipo T hasta el Objeto en la jerarquía de clases?

StackOverflow https://stackoverflow.com/questions/1006192

  •  06-07-2019
  •  | 
  •  

Pregunta

Estoy intentando reutilizar un código existente ... pero sin éxito. Aquí está el fragmento de código:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Reflection;

namespace GenApp.Utils.Reflection
{
    class FieldTraverser
    {


        public static string SearchFieldValue(object obj, int MaxLevel, string strFieldMeta , ref object fieldValue)
        {
            if (obj == null)
                return null;
            else
            {
                StringBuilder sb = new StringBuilder();
                bool flagShouldStop = false; 
                FieldTraverser.PrivDump(sb, obj, "[ObjectToDump]", 0, MaxLevel , ref flagShouldStop , ref fieldValue);
                return sb.ToString();
            }
        } //eof method 



        public static object GetFieldValue(object obj, string fieldName, ref bool flagShouldStop, ref object objFieldValue)
        {
            FieldInfo fi;
            Type t;

            t = obj.GetType();
            fi = t.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            if (fi == null)
                return null;
            else
            {

                if (fi.Name.Equals(fieldName))
                {
                    objFieldValue = fi.GetValue(obj);
                    flagShouldStop = true;
                }
                return fi.GetValue(obj);
            } //eof else 
        } //eof method 


        protected static void DumpType(string InitialStr, StringBuilder sb, object obj, 
            int level, System.Type t, int maxlevel , ref bool flagShouldStop , ref object objFieldValue
            )
        {
            FieldInfo[] fi;
            fi = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            if (t == typeof(System.Delegate)) return;
            foreach (FieldInfo f in fi)
            {
                PrivDump(sb, f.GetValue(obj), f.Name, level + 1, maxlevel , ref flagShouldStop , ref objFieldValue);
                if (flagShouldStop == true)
                    return; 
            }
            object[] arl;
            int i;
            if (obj is System.Array)
            {
                try
                {
                    arl = (object[])obj;
                    for (i = 0; i < arl.GetLength(0); i++)
                    {
                        PrivDump(sb, arl[i], "[" + i + "]", level + 1, maxlevel, ref flagShouldStop, ref objFieldValue);
                        if (flagShouldStop == true)
                            return; 
                    }
                }
                catch (Exception) { }
            }
        }




        protected static void PrivDump(StringBuilder sb, object obj, string objName, int level, int MaxLevel, ref bool flagShouldStop, ref object objFieldValue)
        {

            if (obj == null)
                return;
            if (MaxLevel >= 0 && level >= MaxLevel)
                return;

            string padstr;
            padstr = "";
            for (int i = 0; i < level; i++)
                if (i < level - 1)
                    padstr += "|";
                else
                    padstr += "+";
            string str;
            string[] strarr;
            Type t;
            t = obj.GetType();
            strarr = new String[7];
            strarr[0] = padstr;
            strarr[1] = objName;
            strarr[2] = " AS ";
            strarr[3] = t.FullName;
            strarr[4] = " = ";
            strarr[5] = obj.ToString();
            strarr[6] = "\r\n";
            sb.Append(String.Concat(strarr));
            if (obj.GetType().BaseType == typeof(ValueType))
                return;
            FieldTraverser.DumpType(padstr, sb, obj, level, t, MaxLevel, ref flagShouldStop , ref objFieldValue);
            Type bt;
            bt = t.BaseType;
            if (bt != null)
            {
                while (!(bt == typeof(Object)))
                {
                    str = bt.FullName;
                    sb.Append(padstr + "(" + str + ")\r\n");
                    FieldTraverser.DumpType(padstr, sb, obj, level, bt, MaxLevel , ref flagShouldStop , ref objFieldValue);
                    bt = bt.BaseType;
                    if (bt != null)
                        continue;
                    break;
                } while (bt != typeof(Object)) ;
            }
        } //eof method 
    }//eof class 
    } //eof namespace 
¿Fue útil?

Solución

Tenga en cuenta que es muy raro que tenga que meterse con FieldInfo ; los campos rara vez son públicos y, por lo general, debería estar usando los PropertyInfo ( GetProperties () ). Sin embargo, GetFields funcionará. Para los campos públicos, solo GetFields () ; para campos privados también necesita BindingFlags :

class Foo {
    public string abc;
}
class Bar : Foo {
    private int def;
}
static class Program {
    static void Main() {
        object obj = new Bar();
        FieldInfo[] fields = obj.GetType().GetFields(
            BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        foreach(FieldInfo field in fields) {
            Console.WriteLine(field.Name + " = " + field.GetValue(obj));
        }
    }
}

Otros consejos

¿Ha intentado especificar BindingFlags.FlattenHierarchy ?

Gracias por las respuestas, estaba intentando hacer algo como esto (todavía no estoy seguro de que .ToString () sea la mejor manera de comparar los valores de un campo:

using System;
using System.Reflection; 


class Foo
{
    public string abc;
}
class Bar : Foo
{
    private int def = 0;
}
static class Program
{
    static void Main()
    {
        object obj = new Bar();
        object objShouldNotHaveIt = new Foo();
        object objShouldHaveIt = new Bar();

            string myQuestion = "How-to get a System.Collections.Generic.List<FieldInfo> list which holds all FieldInfo’s of an object of a Type T up to the Object in the class hierarchy in C# ?"; 


        if (Program.SearchFieldByValue(objShouldNotHaveIt, "def", 0))
            Console.WriteLine(" NOK"); 

        if ( Program.SearchFieldByValue(objShouldHaveIt , "def" , 0 ))
            Console.WriteLine(" OK ");

            Console.WriteLine("Is a " + myQuestion.Length.ToString() + " chars long string considered as long question ? "); 



        Console.ReadLine();
    } //eof main 


    public static bool SearchFieldByValue ( object obj , string strFieldName , object objFieldValue ) 
    {

        FieldInfo[] fields = obj.GetType().GetFields(
        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

        foreach (FieldInfo field in fields)
        {
            object objFieldValueReflected = field.GetValue(obj) ; 
            Console.WriteLine(field.Name + " = " + field.GetValue(obj));
            if (objFieldValueReflected != null && objFieldValue.ToString().Equals(objFieldValueReflected.ToString()))
                return true;
            else
                continue; 
        }
        return false; 

    } //eof method 






} //eof class 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top