Find a private field with Reflection?

前端 未结 10 1187
自闭症患者
自闭症患者 2020-11-22 16:17

Given this class

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

    public string BigBar
    {
        ge         


        
相关标签:
10条回答
  • 2020-11-22 16:48

    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.

    0 讨论(0)
  • 2020-11-22 16:48

    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);
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:49
    typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
    
    0 讨论(0)
  • 2020-11-22 16:52

    You can do it just like with a property:

    FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance);
    if (fi.GetCustomAttributes(typeof(SomeAttribute)) != null)
        ...
    
    0 讨论(0)
  • 2020-11-22 16:52

    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;
            }
        }
    
    0 讨论(0)
  • 2020-11-22 16:54

    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.

    0 讨论(0)
提交回复
热议问题