2013-12-17 28 views
5

我有一個結構,有大量的命名布爾成員。 (爲了舉例,請留下良好的實踐和現在的考慮)。使用反射設置對象的所有布爾成員

我想將這些值隨機設置爲true或false,僅用於測試目的。

我該如何通過反射來做到這一點?

這是我到目前爲止有:

 Random r = new Random(); 
     foreach (var bool_field in state.GetType().GetFields().Where(x => x.GetType() == false.GetType())) 
     { 
      bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false); 
     } 

不幸的是,它永遠不會進入循環。

UPDATE 1:

這裏是SystemState結構的樣子,這是狀態變量的類型。它充滿了布爾汽車的屬性。

public struct SystemState 
{ 
    ... 
    public bool CanYouHelpMeOnThisOne { get; set; } 
    ... 
} 

更新2:

貼在下面的解決方案似乎不錯,但它不工作。原因是SystemState是一個結構而不是類。因此,它是一個值類型而不是引用類型,因此調用SetValue方法不起作用。將SystemState更改爲類後,以下解決方案可以很好地工作。

現在有沒有其他的方式來實現這一點,而無需將SystemState更改爲類?

+1

@horgh:假設他在那裏有一些'bool'成員。 –

+1

只是一個方面說明:因爲你知道在編譯時你想設置'布爾'字段,所以我會使用'typeof(布爾)'而不是'false.GetType()'。 –

回答

8

起初,你需要更改Where條款:

x => x.FieldType == false.GetType() 

由於x類型是FieldInfo


自從上次OP的編輯這不是場那裏,但性能。因此,您應該使用GetProperties來獲取屬性列表,並比較PropertyType,因爲x將是PropertyInfo。另外SetValue方法會有另一個簽名。

foreach (var bool_field in state.GetType() 
           .GetProperties() 
           .Where(x => x.PropertyType == false.GetType())) 
{ 
    bool_field.SetValue(state, r.Next() % 2 == 0 ? true : false, null); 
} 

基於OP的評論,如果你想訪問支持字段,你可以使用下面的代碼:

var fs = state.GetType() 
       .GetFields(BindingFlags.Instance | BindingFlags.NonPublic) 
       .Where(x => x.FieldType == typeof(bool)); 
foreach (var f in fs) 
{ 
    f.SetValue(state, true); 
} 

GetFields不帶參數的重載返回的所有公共領域的當前類型。雖然在你的情況下,你需要private,所以使用Type.GetFields Method (BindingFlags)與合適的BindingFlags

+0

據我所知,在裝配層面上,每個自動屬性都有一個後臺字段。它們沒有被Type的GetFields()方法選中? – VSZM

+0

你可以用你現在的代碼輕鬆地檢查它。只記得把'x.GetType()'改爲'x.FieldType' – horgh

+0

除了直接使用後臺字段看起來並不好。 – horgh