2008-09-18 33 views
173

鑑於該類用反射找到一個私人領域?

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

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

我想要找的私人物品_bar,我與一個屬性標記。那可能嗎?

我已經完成了這個屬性,我已經找了一個屬性,但從來沒有私人成員字段。

什麼是綁定標誌,我需要設置獲取私人領域?

+0

@Nescio:你能擴展爲什麼你會採取這種方法? ...好處?或者只是偏好? :) – IAbstract 2012-01-21 20:17:59

回答

212

使用BindingFlags.NonPublicBindingFlags.Instance標誌

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

我只能通過提供「BindingFlags.Instance」綁定標誌來獲得此功能。 – 2008-09-19 15:28:39

+8

我很樂意刪除我的答案,但它被標記爲「已接受」。 – 2009-01-29 19:11:34

+1

我已修復您的答案。否則它太混亂了。安倍海德布雷希特的答案是最完整的。 – 2009-03-05 12:28:53

4

是的,但是您需要設置綁定標誌以搜索私有字段(如果您正在尋找類實例外的成員)。

你需要的結合標誌是:System.Reflection.BindingFlags.NonPublic

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

我不會知道該字段的名稱。我想在沒有名字的情況下找到它,並在該屬性上找到它。 – 2008-09-18 19:22:34

+0

要查找字段名稱,在Visual Studio中很容易。在變量處設置斷點,查看其字段(包括私有,通常以m_fieldname開頭)。將該m_fieldname替換爲上面的命令。 – 2017-11-24 07:54:18

156

你可以做到這一點,就像一個屬性:

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

對不起,極端的necro-posting,但是這把我扔了。如果找不到屬性,GetCustomAttributes(Type)將不返回null,它只是返回一個空數組。 – amnesia 2017-01-30 17:28:47

24

有一件事情你需要注意的時候反思私有te成員是,如果您的應用程序運行在中等信任(例如,當您在共享主機環境中運行時),它將不會找到它們 - BindingFlags.NonPublic選項將被忽略。

2

我在谷歌上搜索這個時遇到了這個,所以我意識到我在碰撞一箇舊帖子。但是GetCustomAttributes需要兩個參數。

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

第二個參數指定你是否希望搜索的繼承層次

29

獲取私有變量的值,使用反射:

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

使用反射私有變量設定值

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

其中objectForFooClass是非空實例爲類類型Foo。

5

我用這個方法親自

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

下面是簡單的得到一些推廣方法和設置私有字段和屬性(與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; 
     } 
    } 
1

你可以有一個擴展方法來得到任何私人領域的任何類型:

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

然後訪問任意類型的私有字段:

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