Frage

In Anbetracht dieser Klasse

class Foo
{
    // Want to find _bar with reflection
    [SomeAttribute]
    private string _bar;

    public string BigBar
    {
        get { return this._bar; }
    }
}

Ich möchte das private Element _bar finden, die ich mit einem Attribut markieren. Ist das möglich?

Ich habe dies mit Eigenschaften getan, wo ich für ein Attribut ausgesehen habe, aber nie ein privates Mitglied Feld.

Was sind die Bindung Flaggen, die ich brauche zu setzen, die privaten Felder zu bekommen?

War es hilfreich?

Lösung

Verwenden BindingFlags.NonPublic und BindingFlags.Instance Flags

FieldInfo[] fields = myType.GetFields(
                         BindingFlags.NonPublic | 
                         BindingFlags.Instance);

Andere Tipps

Sie können es genauso wie mit einer Eigenschaft:

FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi.GetCustomAttributes(typeof(SomeAttribute)) != null)
    ...

Get Privatvariablenwert mit Reflexion:

var _barVariable = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectForFooClass);

Sollwert für die private Variable Reflexion:

typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectForFoocClass, "newValue");

Wo objectForFooClass ist eine nicht null-Instanz für den Klassentyp Foo.

Eine Sache, die Sie sich bewusst sein müssen, wenn sie auf private Mitglieder widerspiegelt, ist, dass, wenn Ihre Anwendung ist in mittlerer Vertrauenswürdigkeit (wie zum Beispiel, wenn Sie auf einem Shared-Hosting-Umgebung ausgeführt wird) ausgeführt wird, wird es sie nicht finden -. die BindingFlags.NonPublic Option wird einfach ignoriert werden

typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)

Nizza Syntax Mit Erweiterungsmethode

Sie können ein beliebiges privates Feld Zugriff von einem beliebigen Typ mit Code wie folgt:

Foo foo = new Foo();
string c = foo.GetFieldValue<string>("_bar");

Für die Sie benötigen, eine Erweiterungsmethode zu definieren, die die Arbeit für Sie tun:

public static class ReflectionExtensions {
    public static T GetFieldValue<T>(this object obj, string name) {
        // Set the flags so that private and public fields from instances will be found
        var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
        var field = obj.GetType().GetField(name, bindingFlags);
        return (T)field?.GetValue(obj);
    }
}

Ich benutze diese Methode persönlich

if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any()))
{ 
    // do stuff
}

Ja, aber müssen Sie Ihre Bindung Flags setzen für den privaten Feldern suchen (wenn Ihr für das Mitglied außerhalb der Klasseninstanz suchen).

Die Bindung Flagge müssen Sie ist: System.Reflection.BindingFlags.NonPublic

Hier sind einige Erweiterungsmethoden für einfache get und set private Felder und Eigenschaften (Eigenschaften mit Setter):

Anwendungsbeispiel:

    public class Foo
    {
        private int Bar = 5;
    }

    var targetObject = new Foo();
    var barValue = targetObject.GetMemberValue("Bar");//Result is 5
    targetObject.SetMemberValue("Bar", 10);//Sets Bar to 10

Code:

    /// <summary>
    /// Extensions methos for using reflection to get / set member values
    /// </summary>
    public static class ReflectionExtensions
    {
        /// <summary>
        /// Gets the public or private member using reflection.
        /// </summary>
        /// <param name="obj">The source target.</param>
        /// <param name="memberName">Name of the field or property.</param>
        /// <returns>the value of member</returns>
        public static object GetMemberValue(this object obj, string memberName)
        {
            var memInf = GetMemberInfo(obj, memberName);

            if (memInf == null)
                throw new System.Exception("memberName");

            if (memInf is System.Reflection.PropertyInfo)
                return memInf.As<System.Reflection.PropertyInfo>().GetValue(obj, null);

            if (memInf is System.Reflection.FieldInfo)
                return memInf.As<System.Reflection.FieldInfo>().GetValue(obj);

            throw new System.Exception();
        }

        /// <summary>
        /// Gets the public or private member using reflection.
        /// </summary>
        /// <param name="obj">The target object.</param>
        /// <param name="memberName">Name of the field or property.</param>
        /// <returns>Old Value</returns>
        public static object SetMemberValue(this object obj, string memberName, object newValue)
        {
            var memInf = GetMemberInfo(obj, memberName);


            if (memInf == null)
                throw new System.Exception("memberName");

            var oldValue = obj.GetMemberValue(memberName);

            if (memInf is System.Reflection.PropertyInfo)
                memInf.As<System.Reflection.PropertyInfo>().SetValue(obj, newValue, null);
            else if (memInf is System.Reflection.FieldInfo)
                memInf.As<System.Reflection.FieldInfo>().SetValue(obj, newValue);
            else
                throw new System.Exception();

            return oldValue;
        }

        /// <summary>
        /// Gets the member info
        /// </summary>
        /// <param name="obj">source object</param>
        /// <param name="memberName">name of member</param>
        /// <returns>instanse of MemberInfo corresponsing to member</returns>
        private static System.Reflection.MemberInfo GetMemberInfo(object obj, string memberName)
        {
            var prps = new System.Collections.Generic.List<System.Reflection.PropertyInfo>();

            prps.Add(obj.GetType().GetProperty(memberName,
                                               System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance |
                                               System.Reflection.BindingFlags.FlattenHierarchy));
            prps = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where( prps,i => !ReferenceEquals(i, null)));
            if (prps.Count != 0)
                return prps[0];

            var flds = new System.Collections.Generic.List<System.Reflection.FieldInfo>();

            flds.Add(obj.GetType().GetField(memberName,
                                            System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance |
                                            System.Reflection.BindingFlags.FlattenHierarchy));

            //to add more types of properties

            flds = System.Linq.Enumerable.ToList(System.Linq.Enumerable.Where(flds, i => !ReferenceEquals(i, null)));

            if (flds.Count != 0)
                return flds[0];

            return null;
        }

        [System.Diagnostics.DebuggerHidden]
        private static T As<T>(this object obj)
        {
            return (T)obj;
        }
    }

Ich kam in diesem, während für diese Suche auf Google, so merke ich, ich einen alten Post bin stoßen. Doch das GetCustomAttributes erfordert zwei params.

typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.GetCustomAttributes(typeof(SomeAttribute), false).Length > 0);

Der zweite Parameter gibt, ob Sie die Vererbungshierarchie suchen möchten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top