279

Given this class

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

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

I want to find the private item _bar that I will mark with a attribute. Is that possible?

I have done this with properties where I have looked for an attribute, but never a private member field.

What are the binding flags that I need to set to get the private fields?

0

11 Answers 11

352

Use BindingFlags.NonPublic and BindingFlags.Instance flags

FieldInfo[] fields = myType.GetFields(
                         BindingFlags.NonPublic | 
                         BindingFlags.Instance);
5
  • 16
    I could only get this to work by also supplying the "BindingFlags.Instance" binding flag. Sep 19, 2008 at 15:28
  • 2
    I have fixed your answer. It's too confusing otherwise. Abe Heidebrecht's answer was the most complete though. Mar 5, 2009 at 12:28
  • 2
    Works great - FYI VB.NET version Me.GetType().GetFields(Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
    – gg.
    May 27, 2009 at 7:36
  • 3
    Using the instance binding flag is only if you want to get instance methods. If you wanted to get a private static method you can use (BindingFlags.NonPublic | BindingFlags.Static)
    – ksun
    Dec 11, 2014 at 23:12
  • BindingFlags.Instance trips me EVERY time I use reflection on non-public members. If you use GetFields() with Default=0 BindingFlags, you get instance members automatically. But when you set a binding flag explicitly, it deletes the default inclusion of instance members. It makes no sense. Flags enums should be additive.
    – Leaky
    Jan 31, 2021 at 15:06
181

You can do it just like with a property:

FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi.GetCustomAttribute(typeof(SomeAttribute)) != null)
    ...
1
  • 14
    Sorry for extreme necro-posting, but this threw me off. GetCustomAttributes(Type) will not return null if the attribute isn't found, it simply returns an empty array.
    – amnesia
    Jan 30, 2017 at 17:28
66

Get private variable's value using Reflection:

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

Set value for private variable using Reflection:

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

Where objectForFooClass is a non null instance for the class type Foo.

1
43

Nice Syntax With Extension Method

You can access any private field of an arbitrary type with code like this:

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

For that you need to define an extension method that will do the work for you:

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);
    }
}
1
  • 1
    Dude, this was PERFECT for accessing a protected variable without exposing it to NLua in my code! Awesome!
    – tayoung
    Feb 1, 2018 at 4:31
26

One thing that you need to be aware of when reflecting on private members is that if your application is running in medium trust (as, for instance, when you are running on a shared hosting environment), it won't find them -- the BindingFlags.NonPublic option will simply be ignored.

2
  • jammycakes could you please give an example of shared hosting environment? i'm thinking iis with multiple apps is what your're getting? Aug 14, 2015 at 1:56
  • 1
    I'm talking about where IIS is locked down to partial trust at the machine.config level. You usually only find this on cheap-and-nasty shared web hosting plans these days (the likes of which I no longer use) -- if you have full control over your server then it won't really be relevant since full trust is the default.
    – jammycakes
    Aug 14, 2015 at 11:16
19
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
2
  • I won't know the name of the field. I want to find it without the name and when the attribute is on it. Sep 18, 2008 at 19:22
  • To find the field name, it's easy to do in Visual Studio. Set breakpoint at the variable, view its fields (including the private, usually started with m_fieldname). Replace that m_fieldname in to the command above.
    – Hao Nguyen
    Nov 24, 2017 at 7:54
7

Here is some extension methods for simple get and set private fields and properties (properties with setter):

usage example:

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

I use this method personally

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

Yes, however you will need to set your Binding flags to search for private fields (if your looking for the member outside of the class instance).

The binding flag you will need is: System.Reflection.BindingFlags.NonPublic

4

If your .Net framework is greater than 4.5. You can use GetRuntimeFields method.

This method returns all fields that are defined on the specified type, including inherited, non-public, instance, and static fields.

https://learn.microsoft.com/en-us/dotnet/api/system.reflection.runtimereflectionextensions.getruntimefields?view=net-6.0

var foo = new Foo();
var fooFields = foo.GetType().GetRuntimeFields()
2

I came across this while searching for this on google so I realise I'm bumping an old post. However the GetCustomAttributes requires two params.

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

The second parameter specifies whether or not you wish to search the inheritance hierarchy

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.