find一个私人领域与思考?
给这个class
class Foo { // Want to find _bar with reflection [SomeAttribute] private string _bar; public string BigBar { get { return this._bar; } } }
我想find私人项目_bar,我将用一个属性标记。 那可能吗?
我已经做了这样的属性,我已经找了一个属性,但从来没有私人成员字段。
什么是绑定标志,我需要设置获取私人领域?
使用BindingFlags.NonPublic
和BindingFlags.Instance
标志
FieldInfo[] fields = myType.GetFields( BindingFlags.NonPublic | BindingFlags.Instance);
你可以做就像一个属性:
FieldInfo fi = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance); if (fi.GetCustomAttributes(typeof(SomeAttribute)) != null) ...
使用reflection获取私有variables的值:
var _barVariable = typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(objectForFooClass);
使用reflection设置私有variables的值:
typeof(Foo).GetField("_bar", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(objectForFoocClass, "newValue");
其中objectForFooClass是类types为Foo的非空实例。
在对私有成员进行反思时,需要注意的一件事是,如果您的应用程序以中等信任运行(例如,当您在共享主机环境中运行时),则不会find它们 – BindingFlags.NonPublic选项将被忽略。
typeof(MyType).GetField("fieldName", BindingFlags.NonPublic | BindingFlags.Instance)
我个人使用这个方法
if (typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Any(c => c.GetCustomAttributes(typeof(SomeAttribute), false).Any())) { // do stuff }
是的,但是您需要设置绑定标志来search私有字段(如果您正在寻找类实例外的成员)。
您需要的绑定标志是:System.Reflection.BindingFlags.NonPublic
下面是一些简单的获取和设置私有字段和属性(使用setter的属性)的扩展方法:
用法示例:
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
码:
/// <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; } }
我在谷歌上search这个时遇到了这个,所以我意识到我正在碰撞一个旧的post。 但是GetCustomAttributes需要两个参数。
typeof(Foo).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Where(x => x.GetCustomAttributes(typeof(SomeAttribute), false).Length > 0);
第二个参数指定是否希望searchinheritance层次结构
你可以有一个扩展方法来获得任何types的私人领域:
public static T GetFieldValue<T>(this object obj, string name) { var field = obj.GetType().GetField(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); return (T)field?.GetValue(obj); }
然后访问任意types的私有字段:
Foo foo = new Foo(); string c = foo.GetFieldValue<string>("_bar");