可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
Use BindingFlags.NonPublic
and BindingFlags.Instance
flags
FieldInfo[] fields = myType.GetFields( BindingFlags.NonPublic | BindingFlags.Instance);
回答2:
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) ...
回答3:
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.
回答4:
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.
回答5:
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
回答6:
I use this method personally
if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any())) { // do stuff }
回答7:
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
回答8:
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:
/// /// Extensions methos for using reflection to get / set member values /// public static class ReflectionExtensions { /// /// Gets the public or private member using reflection. /// /// The source target. /// Name of the field or property. /// the value of member 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().GetValue(obj, null); if (memInf is System.Reflection.FieldInfo) return memInf.As().GetValue(obj); throw new System.Exception(); } /// /// Gets the public or private member using reflection. /// /// The target object. /// Name of the field or property. /// Old Value 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().SetValue(obj, newValue, null); else if (memInf is System.Reflection.FieldInfo) memInf.As().SetValue(obj, newValue); else throw new System.Exception(); return oldValue; } /// /// Gets the member info /// /// source object /// name of member /// instanse of MemberInfo corresponsing to member private static System.Reflection.MemberInfo GetMemberInfo(object obj, string memberName) { var prps = new System.Collections.Generic.List(); 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(); 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(this object obj) { return (T)obj; } }
回答9:
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
回答10:
You can have a extension method to get any private field for any type:
public static T GetFieldValue(this object obj, string name) { var field = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); return (T)field?.GetValue(obj); }
And then access a private field of an arbitrary type:
Foo foo = new Foo(); string c = foo.GetFieldValue("_bar");